diff options
136 files changed, 8429 insertions, 860 deletions
diff --git a/bl1/aarch32/bl1_context_mgmt.c b/bl1/aarch32/bl1_context_mgmt.c index 005d046c..b5a6a341 100644 --- a/bl1/aarch32/bl1_context_mgmt.c +++ b/bl1/aarch32/bl1_context_mgmt.c @@ -102,7 +102,7 @@ static void flush_smc_and_cpu_ctx(void) ******************************************************************************/ void bl1_prepare_next_image(unsigned int image_id) { - unsigned int security_state; + unsigned int security_state, mode = MODE32_svc; image_desc_t *image_desc; entry_point_info_t *next_bl_ep; @@ -117,20 +117,13 @@ void bl1_prepare_next_image(unsigned int image_id) security_state = GET_SECURITY_STATE(next_bl_ep->h.attr); /* Prepare the SPSR for the next BL image. */ - if (security_state == SECURE) { - next_bl_ep->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, - SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); - } else { - /* Use HYP mode if supported else use SVC. */ - if (GET_VIRT_EXT(read_id_pfr1())) { - next_bl_ep->spsr = SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, - SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); - } else { - next_bl_ep->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, - SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); - } + if ((security_state != SECURE) && (GET_VIRT_EXT(read_id_pfr1()))) { + mode = MODE32_hyp; } + next_bl_ep->spsr = SPSR_MODE32(mode, SPSR_T_ARM, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + /* Allow platform to make change */ bl1_plat_set_ep_info(image_id, next_bl_ep); diff --git a/bl1/aarch64/bl1_context_mgmt.c b/bl1/aarch64/bl1_context_mgmt.c index 03263190..8be8830a 100644 --- a/bl1/aarch64/bl1_context_mgmt.c +++ b/bl1/aarch64/bl1_context_mgmt.c @@ -42,7 +42,7 @@ void cm_set_context(void *context, uint32_t security_state) ******************************************************************************/ void bl1_prepare_next_image(unsigned int image_id) { - unsigned int security_state; + unsigned int security_state, mode = MODE_EL1; image_desc_t *image_desc; entry_point_info_t *next_bl_ep; @@ -73,20 +73,13 @@ void bl1_prepare_next_image(unsigned int image_id) cm_set_context(&bl1_cpu_context[security_state], security_state); /* Prepare the SPSR for the next BL image. */ - if (security_state == SECURE) { - next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, - DISABLE_ALL_EXCEPTIONS); - } else { - /* Use EL2 if supported; else use EL1. */ - if (el_implemented(2) != EL_IMPL_NONE) { - next_bl_ep->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, - DISABLE_ALL_EXCEPTIONS); - } else { - next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, - DISABLE_ALL_EXCEPTIONS); - } + if ((security_state != SECURE) && (el_implemented(2) != EL_IMPL_NONE)) { + mode = MODE_EL2; } + next_bl_ep->spsr = SPSR_64(mode, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + /* Allow platform to make change */ bl1_plat_set_ep_info(image_id, next_bl_ep); diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S index b3f59796..40506785 100644 --- a/bl31/aarch64/crash_reporting.S +++ b/bl31/aarch64/crash_reporting.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -45,10 +45,14 @@ non_el3_sys_regs: "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\ "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\ "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\ - "tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\ - "mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\ - "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\ - "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", "" + "tpidrro_el0", "par_el1", "mpidr_el1", "afsr0_el1", "afsr1_el1",\ + "contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\ + "cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", "" + +#if CTX_INCLUDE_AARCH32_REGS +aarch32_regs: + .asciz "dacr32_el2", "ifsr32_el2", "" +#endif /* CTX_INCLUDE_AARCH32_REGS */ panic_msg: .asciz "PANIC in EL3 at x30 = 0x" @@ -299,24 +303,30 @@ func do_crash_reporting mrs x9, tpidr_el1 mrs x10, tpidr_el0 mrs x11, tpidrro_el0 - mrs x12, dacr32_el2 - mrs x13, ifsr32_el2 - mrs x14, par_el1 - mrs x15, mpidr_el1 + mrs x12, par_el1 + mrs x13, mpidr_el1 + mrs x14, afsr0_el1 + mrs x15, afsr1_el1 + bl str_in_crash_buf_print + mrs x8, contextidr_el1 + mrs x9, vbar_el1 + mrs x10, cntp_ctl_el0 + mrs x11, cntp_cval_el0 + mrs x12, cntv_ctl_el0 + mrs x13, cntv_cval_el0 + mrs x14, cntkctl_el1 + mrs x15, sp_el0 bl str_in_crash_buf_print - mrs x8, afsr0_el1 - mrs x9, afsr1_el1 - mrs x10, contextidr_el1 - mrs x11, vbar_el1 - mrs x12, cntp_ctl_el0 - mrs x13, cntp_cval_el0 - mrs x14, cntv_ctl_el0 - mrs x15, cntv_cval_el0 + mrs x8, isr_el1 bl str_in_crash_buf_print - mrs x8, cntkctl_el1 - mrs x9, sp_el0 - mrs x10, isr_el1 + +#if CTX_INCLUDE_AARCH32_REGS + /* Print the AArch32 registers */ + adr x6, aarch32_regs + mrs x8, dacr32_el2 + mrs x9, ifsr32_el2 bl str_in_crash_buf_print +#endif /* CTX_INCLUDE_AARCH32_REGS */ /* Get the cpu specific registers to report */ bl do_cpu_reg_dump diff --git a/common/desc_image_load.c b/common/desc_image_load.c index 405bb834..f2e8f605 100644 --- a/common/desc_image_load.c +++ b/common/desc_image_load.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,6 +9,7 @@ #include <arch_helpers.h> #include <common/bl_common.h> #include <common/desc_image_load.h> +#include <common/tbbr/tbbr_img_def.h> static bl_load_info_t bl_load_info; static bl_params_t next_bl_params; @@ -275,3 +276,47 @@ void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params) } } } + +/******************************************************************************* + * Helper to extract BL32/BL33 entry point info from arg0 passed to BL31, for + * platforms that are only interested in those. Platforms that need to extract + * more information can parse the structures themselves. + ******************************************************************************/ + +void bl31_params_parse_helper(u_register_t param, + entry_point_info_t *bl32_ep_info_out, + entry_point_info_t *bl33_ep_info_out) +{ + bl_params_node_t *node; + bl_params_t *v2 = (void *)(uintptr_t)param; + +#if !ERROR_DEPRECATED + if (v2->h.version == PARAM_VERSION_1) { + struct { /* Deprecated version 1 parameter structure. */ + param_header_t h; + image_info_t *bl31_image_info; + entry_point_info_t *bl32_ep_info; + image_info_t *bl32_image_info; + entry_point_info_t *bl33_ep_info; + image_info_t *bl33_image_info; + } *v1 = (void *)(uintptr_t)param; + assert(v1->h.type == PARAM_BL31); + if (bl32_ep_info_out) + *bl32_ep_info_out = *v1->bl32_ep_info; + if (bl33_ep_info_out) + *bl33_ep_info_out = *v1->bl33_ep_info; + return; + } +#endif /* !ERROR_DEPRECATED */ + + assert(v2->h.version == PARAM_VERSION_2); + assert(v2->h.type == PARAM_BL_PARAMS); + for (node = v2->head; node; node = node->next_params_info) { + if (node->image_id == BL32_IMAGE_ID) + if (bl32_ep_info_out) + *bl32_ep_info_out = *node->ep_info; + if (node->image_id == BL33_IMAGE_ID) + if (bl33_ep_info_out) + *bl33_ep_info_out = *node->ep_info; + } +} diff --git a/docs/components/romlib-design.rst b/docs/components/romlib-design.rst index a70ed17f..d8bc89ce 100644 --- a/docs/components/romlib-design.rst +++ b/docs/components/romlib-design.rst @@ -42,7 +42,7 @@ It is also possible to insert reserved spaces in the list by using the keyword :: - reserved reserved + reserved The reserved spaces can be used to add more functions in the future without affecting the order and location of functions already existing in the jump @@ -71,29 +71,41 @@ image(s) is replaced with the wrapper function. The "library at ROM" contains a necessary init function that initialises the global variables defined by the functions inside "library at ROM". -Scripts -~~~~~~~ +Script +~~~~~~ -There are several scripts that generate the necessary files for the "library at -ROM" to work: +There is a ``romlib_generate.py`` Python script that generates the necessary +files for the "library at ROM" to work. It implements multiple functions: -1. ``gentbl.sh`` - Generates the jump table by parsing the index file. +1. ``romlib_generate.py gentbl [args]`` - Generates the jump table by parsing + the index file. -2. ``genvar.sh`` - Generates the jump table global variable (**not** the jump - table itself) with the absolute address in ROM. This global variable is, - basically, a pointer to the jump table. +2. ``romlib_generator.py genvar [args]`` - Generates the jump table global + variable (**not** the jump table itself) with the absolute address in ROM. + This global variable is, basically, a pointer to the jump table. + +3. ``romlib_generator.py genwrappers [args]`` - Generates a wrapper function for + each entry in the index file except for the ones that contain the keyword + ``patch``. The generated wrapper file is called ``<fn_name>.s``. + +4. ``romlib_generator.py pre [args]`` - Preprocesses the index file which means + it resolves all the include commands in the file recursively. It can also + generate a dependency file of the included index files which can be directly + used in makefiles. + +Each ``romlib_generate.py`` function has its own manual which is accessible by +runing ``romlib_generator.py [function] --help``. + +``romlib_generate.py`` requires Python 3 environment. -3. ``genwrappers.sh`` - Generates a wrapper function for each entry in the index - file except for the ones that contain the keyword ``patch``. The generated - wrapper file is called ``<lib>_<fn_name>.S``. Patching of functions in library at ROM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The ``genwrappers.sh`` script does not generate wrappers for the entries in the -index file that contain the keyword ``patch``. Thus, it allows calling the -function from the actual library by breaking the link to the "library at ROM" -version of this function. +The ``romlib_generator.py genwrappers`` does not generate wrappers for the +entries in the index file that contain the keyword ``patch``. Thus, it allows +calling the function from the actual library by breaking the link to the +"library at ROM" version of this function. The calling sequence for a patched function is as follows: @@ -117,12 +129,6 @@ to showcase the benefits of library at ROM - it's not mandatory. USE_ROMLIB=1 \ all fip -Known issue ------------ -When building library at ROM, a clean build is always required. This is -necessary when changes are made to the index files, e.g. adding new functions, -patching existing ones etc. - -------------- *Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index 72865a51..b327f6ee 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -2762,14 +2762,12 @@ can be obtained from http://github.com/freebsd/freebsd. Storage abstraction layer ------------------------- -In order to improve platform independence and portability an storage abstraction -layer is used to load data from non-volatile platform storage. +In order to improve platform independence and portability a storage abstraction +layer is used to load data from non-volatile platform storage. Currently +storage access is only required by BL1 and BL2 phases and performed inside the +``load_image()`` function in ``bl_common.c``. -Each platform should register devices and their drivers via the Storage layer. -These drivers then need to be initialized by bootloader phases as -required in their respective ``blx_platform_setup()`` functions. Currently -storage access is only required by BL1 and BL2 phases. The ``load_image()`` -function uses the storage layer to access non-volatile platform storage. +.. uml:: ../resources/diagrams/plantuml/io_framework_usage_overview.puml It is mandatory to implement at least one storage driver. For the Arm development platforms the Firmware Image Package (FIP) driver is provided as @@ -2779,13 +2777,25 @@ section in the `User Guide`_). The storage layer is described in the header file is in ``drivers/io/io_storage.c`` and the driver files are located in ``drivers/io/``. +.. uml:: ../resources/diagrams/plantuml/io_arm_class_diagram.puml + Each IO driver must provide ``io_dev_*`` structures, as described in ``drivers/io/io_driver.h``. These are returned via a mandatory registration function that is called on platform initialization. The semi-hosting driver implementation in ``io_semihosting.c`` can be used as an example. -The Storage layer provides mechanisms to initialize storage devices before -IO operations are called. The basic operations supported by the layer +Each platform should register devices and their drivers via the storage +abstraction layer. These drivers then need to be initialized by bootloader +phases as required in their respective ``blx_platform_setup()`` functions. + +.. uml:: ../resources/diagrams/plantuml/io_dev_registration.puml + +The storage abstraction layer provides mechanisms (``io_dev_init()``) to +initialize storage devices before IO operations are called. + +.. uml:: ../resources/diagrams/plantuml/io_dev_init_and_check.puml + +The basic operations supported by the layer include ``open()``, ``close()``, ``read()``, ``write()``, ``size()`` and ``seek()``. Drivers do not have to implement all operations, but each platform must provide at least one driver for a device capable of supporting generic diff --git a/docs/maintainers.rst b/docs/maintainers.rst index 098fc5f5..cbfc652f 100644 --- a/docs/maintainers.rst +++ b/docs/maintainers.rst @@ -112,8 +112,11 @@ HiSilicon Poplar platform port Intel SocFPGA platform ports ---------------------------- :M: Tien Hock Loh <tien.hock.loh@intel.com> -:G: `thloh85-intel` +:G: `thloh85-intel`_ +:M: Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com> +:G: `mabdulha`_ :F: plat/intel/soc +:F: drivers/intel/soc/ MediaTek platform ports ----------------------- diff --git a/docs/plat/intel-agilex.rst b/docs/plat/intel-agilex.rst new file mode 100644 index 00000000..015a195a --- /dev/null +++ b/docs/plat/intel-agilex.rst @@ -0,0 +1,85 @@ +Intel Agilex SoCFPGA +======================== + +Agilex SoCFPGA is a FPGA with integrated quad-core 64-bit Arm Cortex A53 processor. + +Upon boot, Boot ROM loads bl2 into OCRAM. Bl2 subsequently initializes +the hardware, then loads bl31 and bl33 (UEFI) into DDR and boots to bl33. + +:: + + Boot ROM --> Trusted Firmware-A --> UEFI + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link <https://github.com/ARM-software/arm-trusted-firmware>`__ + +- UEFI (to be updated with new upstreamed UEFI): + `link <https://github.com/altera-opensource/uefi-socfpga>`__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 2 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Prepare the AARCH64 toolchain. + +- Build UEFI using Agilex platform as configuration + This will be updated to use an updated UEFI using the latest EDK2 source + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- device=agx + +- Build atf providing the previously generated UEFI as the BL33 image + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- bl2 fip PLAT=agilex + BL33=PEI.ROM + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- dd fip.bin to a A2 partition on the MMC drive to be booted in Agilex + board. + +- Generate a SOF containing bl2 + +.. code:: bash + + aarch64-linux-gnu-objcopy -I binary -O ihex --change-addresses 0xffe00000 bl2.bin bl2.hex + quartus_cpf --bootloader bl2.hex <quartus_generated_sof> <output_sof_with_bl2> + +- Configure SOF to board + +.. code:: bash + + nios2-configure-sof <output_sof_with_bl2> + +Boot trace +---------- + +:: + INFO: DDR: DRAM calibration success. + INFO: ECC is disabled. + NOTICE: BL2: v2.1(debug) + NOTICE: BL2: Built + INFO: BL2: Doing platform setup + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0xffe1c000 + INFO: SPSR = 0x3cd + NOTICE: BL31: v2.1(debug) + NOTICE: BL31: Built + INFO: ARM GICv2 driver initialized + INFO: BL31: Initializing runtime services + WARNING: BL31: cortex_a53 + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x50000 + INFO: SPSR = 0x3c9 diff --git a/docs/plat/rockchip.rst b/docs/plat/rockchip.rst index cee35e42..b7c43fbe 100644 --- a/docs/plat/rockchip.rst +++ b/docs/plat/rockchip.rst @@ -5,6 +5,7 @@ Trusted Firmware-A supports a number of Rockchip ARM SoCs from both AARCH32 and AARCH64 fields. This includes right now: +- px30: Quad-Core Cortex-A53 - rk3288: Quad-Core Cortex-A17 (past A12) - rk3328: Quad-Core Cortex-A53 - rk3368: Octa-Core Cortex-A53 diff --git a/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml b/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml new file mode 100644 index 00000000..53594c2b --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml @@ -0,0 +1,109 @@ +@startuml + +package arm_io_storage { + + class plat_io_policy { + dev_handle : uintptr_t* + image_spec : uintptr_t + {abstract} check() : fctptr + } + + class FIP_IMAGE_ID { + memmap_dev_handle + fip_block_spec + open_memmap() + } + + class BL2_IMAGE_ID{ + fip_dev_handle + bl2_uuid_spec + open_fip() + } + + class xxx_IMAGE_ID{ + fip_dev_handle + xxx_uuid_spec + open_fip() + } + + class arm_io_storage { + fip_dev_con : io_dev_connector_t* + fip_dev_handle : uintptr_t + memmap_dev_con : io_dev_connector_t* + memmap_dev_handle : uintptr_t + + fip_block_spec : io_block_spec_t + + policies : plat_io_policy[1..*] + + -open_fip() + -open_memmap() + + +arm_io_setup() + +plat_get_image_source() + } + + FIP_IMAGE_ID -up-|> plat_io_policy + BL2_IMAGE_ID -up-|> plat_io_policy + xxx_IMAGE_ID -up-|> plat_io_policy + + arm_io_storage *-"1..*" plat_io_policy +} + +package IO { + class io_storage { + io_dev_open() + io_dev_init() + io_dev_close() + + .. synchronous operations .. + io_open() + io_seek() + io_size() + io_read() + io_write() + io_close() + + io_register_device() + } + + class io_fip { + register_io_dev_fip() + .. io_dev_funcs_t interface .. + fip_dev_funcs : io_dev_funcs_t + } + + class io_memmap { + register_io_dev_memmap() + .. io_dev_funcs_t interface .. + memmap_dev_funcs : io_dev_funcs_t + } + + interface io_driver { + io_entity_t + io_dev_info_t + + .. io_dev_connector_t interface .. + dev_open() + + .. io_dev_funcs_t interface .. + type() + open() + seek() + size() + read() + write() + close() + dev_init() + dev_close() + + io_register_device() + } +} +arm_io_storage .. io_driver +arm_io_storage .. io_fip +arm_io_storage .. io_memmap +arm_io_storage .. io_storage + + +@enduml diff --git a/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml b/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml new file mode 100644 index 00000000..2752b332 --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml @@ -0,0 +1,62 @@ +@startuml + +participant arm_io_storage order 1 +participant io_storage order 2 + + -> arm_io_storage : plat_get_image_source(image_id, &dev_handle, &image_spec) + +group init and check device (image_id) + +alt image_id = BL2_IMAGE_ID +note over arm_io_storage + get BL2_IMAGE_ID policy: + - fip_dev_handle + - open_fip() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_fip(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(fip_dev_handle, FIP_IMAGE_ID) + ref over io_storage : dev_init() on fip device + + arm_io_storage -> io_storage : io_open(fip_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on fip device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on fip device + + hnote over arm_io_storage + fip_dev_handle ready + end note +end opt +deactivate arm_io_storage + +else image_id = FIP_IMAGE_ID +activate arm_io_storage +note over arm_io_storage + get FIP_IMAGE_ID policy: + - memmap_dev_handle + - open_memmap() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_memmap(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(memmap_dev_handle, NULL) + ref over io_storage : dev_init() on memmap device + + arm_io_storage -> io_storage : io_open(memmap_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on memmap device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on memmap device + + hnote over arm_io_storage + memmap_dev_handle ready + end note + deactivate arm_io_storage +end opt +deactivate arm_io_storage +end alt + +end group +@enduml diff --git a/docs/resources/diagrams/plantuml/io_dev_registration.puml b/docs/resources/diagrams/plantuml/io_dev_registration.puml new file mode 100644 index 00000000..114c3b77 --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_dev_registration.puml @@ -0,0 +1,52 @@ +@startuml + +participant arm_io_storage order 1 +participant io_storage order 2 +participant io_fip order 3 +participant io_memmap order 4 + + -> arm_io_storage : arm_io_setup() + +group io dev registration + +arm_io_storage -> io_fip : register_io_dev_fip(&fip_dev_con) +io_fip -> io_storage : io_register_device(&dev_info_pool[]) +note over io_storage + devices[dev_count] = (fip_)dev_info_pool + dev_count++ +end note + +arm_io_storage -> io_memmap : register_io_dev_memmap(&memmap_dev_con) +io_memmap -> io_storage : io_register_device(&memmap_dev_info) +note over io_storage + devices[dev_count] = memmap_dev_info + dev_count++ +end note + +arm_io_storage -> io_storage : io_dev_open(fip_dev_con, NULL, fip_dev_handle) + io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on fip device + io_storage -> io_fip : fip_dev_open(dev_spec, dev_info) + note over io_fip + dev_info = one of the + "fip_dev_info" from + dev_info_pool[] + end note +end opt +deactivate io_storage + + +arm_io_storage -> io_storage : io_dev_open(memmap_dev_con, NULL, memmap_dev_handle) +io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on memmap device + io_storage -> io_memmap : memmap_dev_open(dev_spec, dev_info) + note over io_memmap + dev_info = memmap_dev_info + end note +end opt +deactivate io_storage + +end group +@enduml diff --git a/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml b/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml new file mode 100644 index 00000000..eb3e2b4c --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml @@ -0,0 +1,59 @@ +@startuml + +participant bl_common order 1 +participant arm_io_storage order 2 +participant io_storage order 3 + +== Platform Setup == + +bl1_main -> xxx_bl1_setup : bl1_platform_setup() +xxx_bl1_setup -> arm_io_storage : plat_arm_io_setup() + +arm_io_storage -> arm_io_storage : arm_io_setup() +ref over arm_io_storage, io_storage : io device registration + +== Get Image == +bl1_main -> xxx_bl1_setup : bl1_plat_get_next_image_id() +bl1_main <-- xxx_bl1_setup : BL2_IMAGE_ID + +bl1_main -> bl1_main : bl1_load_bl2() +activate bl1_main +bl1_main -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID) +bl1_main <-- plat_bl1_common : BL2_IMAGE_DESC + +bl1_main -> plat_bl1_common : bl1_plat_handle_pre_image_load(BL2_IMAGE_ID) + +bl1_main -> bl_common : load_auth_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> bl_common : load_auth_image_internal(BL2_IMAGE_ID, image_info, is_parent_image) +activate bl_common +bl_common -> bl_common : load_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> arm_io_storage : plat_get_image_source(BL2_IMAGE_ID, &dev_handle, &image_spec) +ref over arm_io_storage, io_storage : init and check device (BL2_IMAGE_ID) +bl_common <-- arm_io_storage : dev_handle + +bl_common -> io_storage : io_open(dev_handle, image_spec, &image_handle) +ref over io_storage : io_open() on fip device +bl_common <-- io_storage : image_handle +bl_common -> io_storage : io_size(image_handle, &image_size) +ref over io_storage : io_size() on fip device +bl_common -> io_storage : io_read(image_handle, image_base, image_size, &bytes_read) +ref over io_storage : io_read() on fip device +bl_common -> io_storage : io_close(image_handle) +ref over io_storage : io_close() on fip device +bl_common -> io_storage : io_dev_close(dev_handle) +ref over io_storage : io_dev_close() on fip device + +deactivate bl_common +deactivate bl_common +deactivate bl_common + +== Prepare Next Image == +bl1_main -> plat_bl1_common : bl1_plat_handle_post_image_load(BL2_IMAGE_ID) + +deactivate bl1_main + +== Jump to next Image == + +@enduml diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h index 0db41458..34036d78 100644 --- a/include/arch/aarch32/arch.h +++ b/include/arch/aarch32/arch.h @@ -294,6 +294,8 @@ #define SPSR_MODE_SHIFT U(0) #define SPSR_MODE_MASK U(0x7) +#define SPSR_SSBS_BIT BIT_32(23) + #define DISABLE_ALL_EXCEPTIONS \ (SPSR_FIQ_BIT | SPSR_IRQ_BIT | SPSR_ABT_BIT) @@ -384,11 +386,12 @@ #define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) #define SPSR_MODE32(mode, isa, endian, aif) \ - (MODE_RW_32 << MODE_RW_SHIFT | \ + ((MODE_RW_32 << MODE_RW_SHIFT | \ ((mode) & MODE32_MASK) << MODE32_SHIFT | \ ((isa) & SPSR_T_MASK) << SPSR_T_SHIFT | \ ((endian) & SPSR_E_MASK) << SPSR_E_SHIFT | \ - ((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT) + ((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT) & \ + (~(SPSR_SSBS_BIT))) /* * TTBR definitions diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index 913b62c5..fa857fb1 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -219,6 +219,13 @@ #define BTI_IMPLEMENTED ULL(1) /* The BTI mechanism is implemented */ +#define ID_AA64PFR1_EL1_MTE_SHIFT U(8) +#define ID_AA64PFR1_EL1_MTE_MASK ULL(0xf) + +#define MTE_UNIMPLEMENTED ULL(0) +#define MTE_IMPLEMENTED_EL0 ULL(1) /* MTE is only implemented at EL0 */ +#define MTE_IMPLEMENTED_ELX ULL(2) /* MTE is implemented at all ELs */ + /* ID_PFR1_EL1 definitions */ #define ID_PFR1_VIRTEXT_SHIFT U(12) #define ID_PFR1_VIRTEXT_MASK U(0xf) @@ -278,6 +285,7 @@ /* SCR definitions */ #define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5)) +#define SCR_ATA_BIT (U(1) << 26) #define SCR_FIEN_BIT (U(1) << 21) #define SCR_API_BIT (U(1) << 17) #define SCR_APK_BIT (U(1) << 16) @@ -411,6 +419,9 @@ #define SPSR_M_AARCH64 U(0x0) #define SPSR_M_AARCH32 U(0x1) +#define SPSR_SSBS_BIT_AARCH64 BIT_64(12) +#define SPSR_SSBS_BIT_AARCH32 BIT_64(23) + #define DISABLE_ALL_EXCEPTIONS \ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) @@ -535,18 +546,20 @@ #define GET_SP(mode) (((mode) >> MODE_SP_SHIFT) & MODE_SP_MASK) #define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) -#define SPSR_64(el, sp, daif) \ - ((MODE_RW_64 << MODE_RW_SHIFT) | \ - (((el) & MODE_EL_MASK) << MODE_EL_SHIFT) | \ - (((sp) & MODE_SP_MASK) << MODE_SP_SHIFT) | \ - (((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)) +#define SPSR_64(el, sp, daif) \ + (((MODE_RW_64 << MODE_RW_SHIFT) | \ + (((el) & MODE_EL_MASK) << MODE_EL_SHIFT) | \ + (((sp) & MODE_SP_MASK) << MODE_SP_SHIFT) | \ + (((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)) & \ + (~(SPSR_SSBS_BIT_AARCH64))) #define SPSR_MODE32(mode, isa, endian, aif) \ - ((MODE_RW_32 << MODE_RW_SHIFT) | \ + (((MODE_RW_32 << MODE_RW_SHIFT) | \ (((mode) & MODE32_MASK) << MODE32_SHIFT) | \ (((isa) & SPSR_T_MASK) << SPSR_T_SHIFT) | \ (((endian) & SPSR_E_MASK) << SPSR_E_SHIFT) | \ - (((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)) + (((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)) & \ + (~(SPSR_SSBS_BIT_AARCH32))) /* * TTBR Definitions diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index 1129b8e4..2f29f487 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -54,4 +54,10 @@ static inline bool is_armv8_5_bti_present(void) ID_AA64PFR1_EL1_BT_MASK) == BTI_IMPLEMENTED; } +static inline unsigned int get_armv8_5_mte_support(void) +{ + return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) & + ID_AA64PFR1_EL1_MTE_MASK); +} + #endif /* ARCH_FEATURES_H */ diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 457dc2a1..eb96df0b 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -11,6 +11,14 @@ #include <common/param_header.h> #include <lib/utils_def.h> +#ifndef __ASSEMBLY__ +#include <stddef.h> +#include <stdint.h> +#include <lib/cassert.h> +#endif /* __ASSEMBLY__ */ + +#include <export/common/bl_common_exp.h> + #define UP U(1) #define DOWN U(0) @@ -21,22 +29,6 @@ #define TOP U(0x1) #define BOTTOM U(0x0) -/* - * The following are used for image state attributes. - * Image can only be in one of the following state. - */ -#define IMAGE_STATE_RESET U(0) -#define IMAGE_STATE_COPIED U(1) -#define IMAGE_STATE_COPYING U(2) -#define IMAGE_STATE_AUTHENTICATED U(3) -#define IMAGE_STATE_EXECUTED U(4) -#define IMAGE_STATE_INTERRUPTED U(5) - -#define IMAGE_ATTRIB_SKIP_LOADING U(0x02) -#define IMAGE_ATTRIB_PLAT_SETUP U(0x04) - -#define INVALID_IMAGE_ID U(0xFFFFFFFF) - /******************************************************************************* * Constants to indicate type of exception to the common exception handler. ******************************************************************************/ @@ -101,11 +93,6 @@ #ifndef __ASSEMBLY__ -#include <stddef.h> -#include <stdint.h> - -#include <lib/cassert.h> - /* * Declarations of linker defined symbols to help determine memory layout of * BL images @@ -165,66 +152,6 @@ typedef struct meminfo { size_t total_size; } meminfo_t; -/***************************************************************************** - * Image info binary provides information from the image loader that - * can be used by the firmware to manage available trusted RAM. - * More advanced firmware image formats can provide additional - * information that enables optimization or greater flexibility in the - * common firmware code - *****************************************************************************/ -typedef struct image_info { - param_header_t h; - uintptr_t image_base; /* physical address of base of image */ - uint32_t image_size; /* bytes read from image file */ - uint32_t image_max_size; -} image_info_t; - -/***************************************************************************** - * The image descriptor struct definition. - *****************************************************************************/ -typedef struct image_desc { - /* Contains unique image id for the image. */ - unsigned int image_id; - /* - * This member contains Image state information. - * Refer IMAGE_STATE_XXX defined above. - */ - unsigned int state; - uint32_t copied_size; /* image size copied in blocks */ - image_info_t image_info; - entry_point_info_t ep_info; -} image_desc_t; - -/* BL image node in the BL image loading sequence */ -typedef struct bl_load_info_node { - unsigned int image_id; - image_info_t *image_info; - struct bl_load_info_node *next_load_info; -} bl_load_info_node_t; - -/* BL image head node in the BL image loading sequence */ -typedef struct bl_load_info { - param_header_t h; - bl_load_info_node_t *head; -} bl_load_info_t; - -/* BL image node in the BL image execution sequence */ -typedef struct bl_params_node { - unsigned int image_id; - image_info_t *image_info; - entry_point_info_t *ep_info; - struct bl_params_node *next_params_info; -} bl_params_node_t; - -/* - * BL image head node in the BL image execution sequence - * It is also used to pass information to next BL image. - */ -typedef struct bl_params { - param_header_t h; - bl_params_node_t *head; -} bl_params_t; - /******************************************************************************* * Function & variable prototypes ******************************************************************************/ diff --git a/include/common/desc_image_load.h b/include/common/desc_image_load.h index e46eb279..b044f3e7 100644 --- a/include/common/desc_image_load.h +++ b/include/common/desc_image_load.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -40,4 +40,9 @@ bl_load_info_t *get_bl_load_info_from_mem_params_desc(void); bl_params_t *get_next_bl_params_from_mem_params_desc(void); void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params); +/* Helper to extract BL32/BL33 entry point info from arg0 passed to BL31. */ +void bl31_params_parse_helper(u_register_t param, + entry_point_info_t *bl32_ep_info_out, + entry_point_info_t *bl33_ep_info_out); + #endif /* DESC_IMAGE_LOAD_H */ diff --git a/include/common/ep_info.h b/include/common/ep_info.h index a09d03ba..6cb903ef 100644 --- a/include/common/ep_info.h +++ b/include/common/ep_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,105 +8,30 @@ #define EP_INFO_H #include <common/param_header.h> -#include <lib/utils_def.h> -#define SECURE U(0x0) -#define NON_SECURE U(0x1) +#ifndef __ASSEMBLY__ +#include <stdint.h> +#include <lib/cassert.h> +#endif /* __ASSEMBLY__ */ + +#include <export/common/ep_info_exp.h> + +#define SECURE EP_SECURE +#define NON_SECURE EP_NON_SECURE #define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE)) -/******************************************************************************* - * Constants that allow assembler code to access members of and the - * 'entry_point_info' structure at their correct offsets. - ******************************************************************************/ -#define ENTRY_POINT_INFO_PC_OFFSET U(0x08) -#ifdef AARCH32 -#define ENTRY_POINT_INFO_LR_SVC_OFFSET U(0x10) -#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x14) -#else -#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x18) -#endif +#define PARAM_EP_SECURITY_MASK EP_SECURITY_MASK -/* The following are used to set/get image attributes. */ -#define PARAM_EP_SECURITY_MASK U(0x1) +#define NON_EXECUTABLE EP_NON_EXECUTABLE +#define EXECUTABLE EP_EXECUTABLE /* Secure or Non-secure image */ -#define GET_SECURITY_STATE(x) ((x) & PARAM_EP_SECURITY_MASK) +#define GET_SECURITY_STATE(x) ((x) & EP_SECURITY_MASK) #define SET_SECURITY_STATE(x, security) \ - ((x) = ((x) & ~PARAM_EP_SECURITY_MASK) | (security)) - -/* Endianness of the image. */ -#define EP_EE_MASK U(0x2) -#define EP_EE_SHIFT U(1) -#define EP_EE_LITTLE U(0x0) -#define EP_EE_BIG U(0x2) -#define EP_GET_EE(x) ((x) & EP_EE_MASK) -#define EP_SET_EE(x, ee) ((x) = ((x) & ~EP_EE_MASK) | (ee)) - -/* Enable or disable access to the secure timer from secure images. */ -#define EP_ST_MASK U(0x4) -#define EP_ST_DISABLE U(0x0) -#define EP_ST_ENABLE U(0x4) -#define EP_GET_ST(x) ((x) & EP_ST_MASK) -#define EP_SET_ST(x, ee) ((x) = ((x) & ~EP_ST_MASK) | (ee)) - -/* Determine if an image is executable or not. */ -#define EP_EXE_MASK U(0x8) -#define NON_EXECUTABLE U(0x0) -#define EXECUTABLE U(0x8) -#define EP_GET_EXE(x) ((x) & EP_EXE_MASK) -#define EP_SET_EXE(x, ee) ((x) = ((x) & ~EP_EXE_MASK) | (ee)) - -/* Flag to indicate the first image that is executed. */ -#define EP_FIRST_EXE_MASK U(0x10) -#define EP_FIRST_EXE U(0x10) -#define EP_GET_FIRST_EXE(x) ((x) & EP_FIRST_EXE_MASK) -#define EP_SET_FIRST_EXE(x, ee) ((x) = ((x) & ~EP_FIRST_EXE_MASK) | (ee)) + ((x) = ((x) & ~EP_SECURITY_MASK) | (security)) #ifndef __ASSEMBLY__ -#include <stdint.h> - -#include <lib/cassert.h> - -typedef struct aapcs64_params { - u_register_t arg0; - u_register_t arg1; - u_register_t arg2; - u_register_t arg3; - u_register_t arg4; - u_register_t arg5; - u_register_t arg6; - u_register_t arg7; -} aapcs64_params_t; - -typedef struct aapcs32_params { - u_register_t arg0; - u_register_t arg1; - u_register_t arg2; - u_register_t arg3; -} aapcs32_params_t; - -/***************************************************************************** - * This structure represents the superset of information needed while - * switching exception levels. The only two mechanisms to do so are - * ERET & SMC. Security state is indicated using bit zero of header - * attribute - * NOTE: BL1 expects entrypoint followed by spsr at an offset from the start - * of this structure defined by the macro `ENTRY_POINT_INFO_PC_OFFSET` while - * processing SMC to jump to BL31. - *****************************************************************************/ -typedef struct entry_point_info { - param_header_t h; - uintptr_t pc; - uint32_t spsr; -#ifdef AARCH32 - uintptr_t lr_svc; - aapcs32_params_t args; -#else - aapcs64_params_t args; -#endif -} entry_point_info_t; - /* * Compile time assertions related to the 'entry_point_info' structure to * ensure that the assembler and the compiler view of the offsets of diff --git a/include/common/param_header.h b/include/common/param_header.h index 0c1503f1..b8852869 100644 --- a/include/common/param_header.h +++ b/include/common/param_header.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,20 +9,14 @@ #include <stdbool.h> -#include <lib/utils_def.h> +#ifndef __ASSEMBLY__ +#include <stdint.h> +#endif /*__ASSEMBLY__*/ -/* Param header types */ -#define PARAM_EP U(0x01) -#define PARAM_IMAGE_BINARY U(0x02) -#define PARAM_BL31 U(0x03) -#define PARAM_BL_LOAD_INFO U(0x04) -#define PARAM_BL_PARAMS U(0x05) -#define PARAM_PSCI_LIB_ARGS U(0x06) -#define PARAM_SP_IMAGE_BOOT_INFO U(0x07) +#include <export/common/param_header_exp.h> -/* Param header version */ -#define VERSION_1 U(0x01) -#define VERSION_2 U(0x02) +#define VERSION_1 PARAM_VERSION_1 +#define VERSION_2 PARAM_VERSION_2 #define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \ (_p)->h.type = (uint8_t)(_type); \ @@ -38,21 +32,4 @@ ._p.h.size = (uint16_t)sizeof(_p_type), \ ._p.h.attr = (uint32_t)(_attr) -#ifndef __ASSEMBLY__ - -#include <stdint.h> - -/*************************************************************************** - * This structure provides version information and the size of the - * structure, attributes for the structure it represents - ***************************************************************************/ -typedef struct param_header { - uint8_t type; /* type of the structure */ - uint8_t version; /* version of this structure */ - uint16_t size; /* size of this structure in bytes */ - uint32_t attr; /* attributes: unused bits SBZ */ -} param_header_t; - -#endif /*__ASSEMBLY__*/ - #endif /* PARAM_HEADER_H */ diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h index 672886de..1701995a 100644 --- a/include/common/tbbr/tbbr_img_def.h +++ b/include/common/tbbr/tbbr_img_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,83 +7,6 @@ #ifndef TBBR_IMG_DEF_H #define TBBR_IMG_DEF_H -#include <lib/utils_def.h> - -/* Firmware Image Package */ -#define FIP_IMAGE_ID U(0) - -/* Trusted Boot Firmware BL2 */ -#define BL2_IMAGE_ID U(1) - -/* SCP Firmware SCP_BL2 */ -#define SCP_BL2_IMAGE_ID U(2) - -/* EL3 Runtime Firmware BL31 */ -#define BL31_IMAGE_ID U(3) - -/* Secure Payload BL32 (Trusted OS) */ -#define BL32_IMAGE_ID U(4) - -/* Non-Trusted Firmware BL33 */ -#define BL33_IMAGE_ID U(5) - -/* Certificates */ -#define TRUSTED_BOOT_FW_CERT_ID U(6) -#define TRUSTED_KEY_CERT_ID U(7) - -#define SCP_FW_KEY_CERT_ID U(8) -#define SOC_FW_KEY_CERT_ID U(9) -#define TRUSTED_OS_FW_KEY_CERT_ID U(10) -#define NON_TRUSTED_FW_KEY_CERT_ID U(11) - -#define SCP_FW_CONTENT_CERT_ID U(12) -#define SOC_FW_CONTENT_CERT_ID U(13) -#define TRUSTED_OS_FW_CONTENT_CERT_ID U(14) -#define NON_TRUSTED_FW_CONTENT_CERT_ID U(15) - -/* Non-Trusted ROM Firmware NS_BL1U */ -#define NS_BL1U_IMAGE_ID U(16) - -/* Trusted FWU Certificate */ -#define FWU_CERT_ID U(17) - -/* Trusted FWU SCP Firmware SCP_BL2U */ -#define SCP_BL2U_IMAGE_ID U(18) - -/* Trusted FWU Boot Firmware BL2U */ -#define BL2U_IMAGE_ID U(19) - -/* Non-Trusted FWU Firmware NS_BL2U */ -#define NS_BL2U_IMAGE_ID U(20) - -/* Secure Payload BL32_EXTRA1 (Trusted OS Extra1) */ -#define BL32_EXTRA1_IMAGE_ID U(21) - -/* Secure Payload BL32_EXTRA2 (Trusted OS Extra2) */ -#define BL32_EXTRA2_IMAGE_ID U(22) - -/* HW_CONFIG (e.g. Kernel DT) */ -#define HW_CONFIG_ID U(23) - -/* TB_FW_CONFIG */ -#define TB_FW_CONFIG_ID U(24) - -/* SOC_FW_CONFIG */ -#define SOC_FW_CONFIG_ID U(25) - -/* TOS_FW_CONFIG */ -#define TOS_FW_CONFIG_ID U(26) - -/* NT_FW_CONFIG */ -#define NT_FW_CONFIG_ID U(27) - -/* GPT Partition */ -#define GPT_IMAGE_ID U(28) - -/* Binary with STM32 header */ -#define STM32_IMAGE_ID U(29) - -/* Define size of the array */ -#define MAX_NUMBER_IDS U(30) +#include <export/common/tbbr/tbbr_img_def_exp.h> #endif /* TBBR_IMG_DEF_H */ diff --git a/include/drivers/gpio.h b/include/drivers/gpio.h index bef62f73..99c18a4b 100644 --- a/include/drivers/gpio.h +++ b/include/drivers/gpio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,15 +7,17 @@ #ifndef GPIO_H #define GPIO_H -#define GPIO_DIR_OUT 0 -#define GPIO_DIR_IN 1 +#include <export/drivers/gpio_exp.h> -#define GPIO_LEVEL_LOW 0 -#define GPIO_LEVEL_HIGH 1 +#define GPIO_DIR_OUT ARM_TF_GPIO_DIR_OUT +#define GPIO_DIR_IN ARM_TF_GPIO_DIR_IN -#define GPIO_PULL_NONE 0 -#define GPIO_PULL_UP 1 -#define GPIO_PULL_DOWN 2 +#define GPIO_LEVEL_LOW ARM_TF_GPIO_LEVEL_LOW +#define GPIO_LEVEL_HIGH ARM_TF_GPIO_LEVEL_HIGH + +#define GPIO_PULL_NONE ARM_TF_GPIO_PULL_NONE +#define GPIO_PULL_UP ARM_TF_GPIO_PULL_UP +#define GPIO_PULL_DOWN ARM_TF_GPIO_PULL_DOWN typedef struct gpio_ops { int (*get_direction)(int gpio); diff --git a/include/export/README b/include/export/README new file mode 100644 index 00000000..2de8d6b3 --- /dev/null +++ b/include/export/README @@ -0,0 +1,33 @@ +All headers under include/export/ are export headers that are intended for +inclusion in third-party code which needs to interact with TF-A data structures +or interfaces. They must follow these special rules: + +- Header guards should start with ARM_TRUSTED_FIRMWARE_ to reduce clash risk. + +- All definitions should be sufficiently namespaced (e.g. with BL_ or TF_) to + make name clashes with third-party code unlikely. + +- They must not #include any headers except other export headers, and those + includes must use relative paths with "../double_quotes.h" notation. + +- They must not rely on any type definitions other that <stdint.h> types defined + in the ISO C standard (i.e. uint64_t is fine, but not u_register_t). They + should still not #include <stdint.h>. Instead, wrapper headers including + export headers need to ensure that they #include <stdint.h> earlier in their + include order. + +- They must not rely on any macro definitions other than those which are + pre-defined by all common compilers (e.g. __ASSEMBLER__ or __aarch64__). + +- They must only contain macro, type and structure definitions, no prototypes. + +- They should avoid using integer types with architecture-dependent widths + (e.g. long, uintptr_t, pointer types) where possible. (Some existing export + headers are violating this for now.) + +- Their names should always end in "_exp.h". + +- Normal TF-A code should never include export headers directly. Instead, it + should include a wrapper header that ensures the export header is included in + the right manner. (The wrapper header for include/export/x/y/z_exp.h should + normally be placed at include/x/y/z.h.) diff --git a/include/export/common/bl_common_exp.h b/include/export/common/bl_common_exp.h new file mode 100644 index 00000000..8f090176 --- /dev/null +++ b/include/export/common/bl_common_exp.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "ep_info_exp.h" +#include "tbbr/tbbr_img_def_exp.h" + +/* + * The following are used for image state attributes. + * Image can only be in one of the following state. + */ +#define IMAGE_STATE_RESET U(0) +#define IMAGE_STATE_COPIED U(1) +#define IMAGE_STATE_COPYING U(2) +#define IMAGE_STATE_AUTHENTICATED U(3) +#define IMAGE_STATE_EXECUTED U(4) +#define IMAGE_STATE_INTERRUPTED U(5) + +#define IMAGE_ATTRIB_SKIP_LOADING U(0x02) +#define IMAGE_ATTRIB_PLAT_SETUP U(0x04) + +#define INVALID_IMAGE_ID U(0xFFFFFFFF) + +#ifndef __ASSEMBLER__ + +/***************************************************************************** + * Image info binary provides information from the image loader that + * can be used by the firmware to manage available trusted RAM. + * More advanced firmware image formats can provide additional + * information that enables optimization or greater flexibility in the + * common firmware code + *****************************************************************************/ +typedef struct image_info { + param_header_t h; + uintptr_t image_base; /* physical address of base of image */ + uint32_t image_size; /* bytes read from image file */ + uint32_t image_max_size; +} image_info_t; + +/* BL image node in the BL image execution sequence */ +typedef struct bl_params_node { + unsigned int image_id; + image_info_t *image_info; + entry_point_info_t *ep_info; + struct bl_params_node *next_params_info; +} bl_params_node_t; + +/* + * BL image head node in the BL image execution sequence + * It is also used to pass information to next BL image. + */ +typedef struct bl_params { + param_header_t h; + bl_params_node_t *head; +} bl_params_t; + +/***************************************************************************** + * The image descriptor struct definition. + *****************************************************************************/ +typedef struct image_desc { + /* Contains unique image id for the image. */ + unsigned int image_id; + /* + * This member contains Image state information. + * Refer IMAGE_STATE_XXX defined above. + */ + unsigned int state; + uint32_t copied_size; /* image size copied in blocks */ + image_info_t image_info; + entry_point_info_t ep_info; +} image_desc_t; + +/* BL image node in the BL image loading sequence */ +typedef struct bl_load_info_node { + unsigned int image_id; + image_info_t *image_info; + struct bl_load_info_node *next_load_info; +} bl_load_info_node_t; + +/* BL image head node in the BL image loading sequence */ +typedef struct bl_load_info { + param_header_t h; + bl_load_info_node_t *head; +} bl_load_info_t; + +#endif /* __ASSEMBLER__ */ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H */ diff --git a/include/export/common/ep_info_exp.h b/include/export/common/ep_info_exp.h new file mode 100644 index 00000000..4c703e6d --- /dev/null +++ b/include/export/common/ep_info_exp.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../lib/utils_def_exp.h" +#include "param_header_exp.h" + +/******************************************************************************* + * Constants that allow assembler code to access members of and the + * 'entry_point_info' structure at their correct offsets. + ******************************************************************************/ +#define ENTRY_POINT_INFO_PC_OFFSET U(0x08) +#ifdef __aarch64__ +#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x18) +#else +#define ENTRY_POINT_INFO_LR_SVC_OFFSET U(0x10) +#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x14) +#endif + +/* Security state of the image. */ +#define EP_SECURITY_MASK U(0x1) +#define EP_SECURITY_SHIFT U(0) +#define EP_SECURE U(0x0) +#define EP_NON_SECURE U(0x1) + +/* Endianness of the image. */ +#define EP_EE_MASK U(0x2) +#define EP_EE_SHIFT U(1) +#define EP_EE_LITTLE U(0x0) +#define EP_EE_BIG U(0x2) +#define EP_GET_EE(x) ((x) & EP_EE_MASK) +#define EP_SET_EE(x, ee) ((x) = ((x) & ~EP_EE_MASK) | (ee)) + +/* Enable or disable access to the secure timer from secure images. */ +#define EP_ST_MASK U(0x4) +#define EP_ST_SHIFT U(2) +#define EP_ST_DISABLE U(0x0) +#define EP_ST_ENABLE U(0x4) +#define EP_GET_ST(x) ((x) & EP_ST_MASK) +#define EP_SET_ST(x, ee) ((x) = ((x) & ~EP_ST_MASK) | (ee)) + +/* Determine if an image is executable or not. */ +#define EP_EXE_MASK U(0x8) +#define EP_EXE_SHIFT U(3) +#define EP_NON_EXECUTABLE U(0x0) +#define EP_EXECUTABLE U(0x8) +#define EP_GET_EXE(x) ((x) & EP_EXE_MASK) +#define EP_SET_EXE(x, ee) ((x) = ((x) & ~EP_EXE_MASK) | (ee)) + +/* Flag to indicate the first image that is executed. */ +#define EP_FIRST_EXE_MASK U(0x10) +#define EP_FIRST_EXE_SHIFT U(4) +#define EP_FIRST_EXE U(0x10) +#define EP_GET_FIRST_EXE(x) ((x) & EP_FIRST_EXE_MASK) +#define EP_SET_FIRST_EXE(x, ee) ((x) = ((x) & ~EP_FIRST_EXE_MASK) | (ee)) + +#ifndef __ASSEMBLER__ + +typedef struct aapcs64_params { + uint64_t arg0; + uint64_t arg1; + uint64_t arg2; + uint64_t arg3; + uint64_t arg4; + uint64_t arg5; + uint64_t arg6; + uint64_t arg7; +} aapcs64_params_t; + +typedef struct aapcs32_params { + uint32_t arg0; + uint32_t arg1; + uint32_t arg2; + uint32_t arg3; +} aapcs32_params_t; + +/***************************************************************************** + * This structure represents the superset of information needed while + * switching exception levels. The only two mechanisms to do so are + * ERET & SMC. Security state is indicated using bit zero of header + * attribute + * NOTE: BL1 expects entrypoint followed by spsr at an offset from the start + * of this structure defined by the macro `ENTRY_POINT_INFO_PC_OFFSET` while + * processing SMC to jump to BL31. + *****************************************************************************/ +typedef struct entry_point_info { + param_header_t h; + uintptr_t pc; + uint32_t spsr; +#ifdef __aarch64__ + aapcs64_params_t args; +#else + uintptr_t lr_svc; + aapcs32_params_t args; +#endif +} entry_point_info_t; + +#endif /*__ASSEMBLER__*/ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H */ diff --git a/include/export/common/param_header_exp.h b/include/export/common/param_header_exp.h new file mode 100644 index 00000000..15bb6f2a --- /dev/null +++ b/include/export/common/param_header_exp.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../lib/utils_def_exp.h" + +/* Param header types */ +#define PARAM_EP U(0x01) +#define PARAM_IMAGE_BINARY U(0x02) +#define PARAM_BL31 U(0x03) +#define PARAM_BL_LOAD_INFO U(0x04) +#define PARAM_BL_PARAMS U(0x05) +#define PARAM_PSCI_LIB_ARGS U(0x06) +#define PARAM_SP_IMAGE_BOOT_INFO U(0x07) + +/* Param header version */ +#define PARAM_VERSION_1 U(0x01) +#define PARAM_VERSION_2 U(0x02) + +#ifndef __ASSEMBLER__ + +/*************************************************************************** + * This structure provides version information and the size of the + * structure, attributes for the structure it represents + ***************************************************************************/ +typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ +} param_header_t; + +#endif /*__ASSEMBLER__*/ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H */ diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h new file mode 100644 index 00000000..ff0d16c7 --- /dev/null +++ b/include/export/common/tbbr/tbbr_img_def_exp.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../lib/utils_def_exp.h" + +/* Firmware Image Package */ +#define FIP_IMAGE_ID U(0) + +/* Trusted Boot Firmware BL2 */ +#define BL2_IMAGE_ID U(1) + +/* SCP Firmware SCP_BL2 */ +#define SCP_BL2_IMAGE_ID U(2) + +/* EL3 Runtime Firmware BL31 */ +#define BL31_IMAGE_ID U(3) + +/* Secure Payload BL32 (Trusted OS) */ +#define BL32_IMAGE_ID U(4) + +/* Non-Trusted Firmware BL33 */ +#define BL33_IMAGE_ID U(5) + +/* Certificates */ +#define TRUSTED_BOOT_FW_CERT_ID U(6) +#define TRUSTED_KEY_CERT_ID U(7) + +#define SCP_FW_KEY_CERT_ID U(8) +#define SOC_FW_KEY_CERT_ID U(9) +#define TRUSTED_OS_FW_KEY_CERT_ID U(10) +#define NON_TRUSTED_FW_KEY_CERT_ID U(11) + +#define SCP_FW_CONTENT_CERT_ID U(12) +#define SOC_FW_CONTENT_CERT_ID U(13) +#define TRUSTED_OS_FW_CONTENT_CERT_ID U(14) +#define NON_TRUSTED_FW_CONTENT_CERT_ID U(15) + +/* Non-Trusted ROM Firmware NS_BL1U */ +#define NS_BL1U_IMAGE_ID U(16) + +/* Trusted FWU Certificate */ +#define FWU_CERT_ID U(17) + +/* Trusted FWU SCP Firmware SCP_BL2U */ +#define SCP_BL2U_IMAGE_ID U(18) + +/* Trusted FWU Boot Firmware BL2U */ +#define BL2U_IMAGE_ID U(19) + +/* Non-Trusted FWU Firmware NS_BL2U */ +#define NS_BL2U_IMAGE_ID U(20) + +/* Secure Payload BL32_EXTRA1 (Trusted OS Extra1) */ +#define BL32_EXTRA1_IMAGE_ID U(21) + +/* Secure Payload BL32_EXTRA2 (Trusted OS Extra2) */ +#define BL32_EXTRA2_IMAGE_ID U(22) + +/* HW_CONFIG (e.g. Kernel DT) */ +#define HW_CONFIG_ID U(23) + +/* TB_FW_CONFIG */ +#define TB_FW_CONFIG_ID U(24) + +/* SOC_FW_CONFIG */ +#define SOC_FW_CONFIG_ID U(25) + +/* TOS_FW_CONFIG */ +#define TOS_FW_CONFIG_ID U(26) + +/* NT_FW_CONFIG */ +#define NT_FW_CONFIG_ID U(27) + +/* GPT Partition */ +#define GPT_IMAGE_ID U(28) + +/* Binary with STM32 header */ +#define STM32_IMAGE_ID U(29) + +/* Define size of the array */ +#define MAX_NUMBER_IDS U(30) + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */ diff --git a/include/export/drivers/gpio_exp.h b/include/export/drivers/gpio_exp.h new file mode 100644 index 00000000..a37f1907 --- /dev/null +++ b/include/export/drivers/gpio_exp.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#define ARM_TF_GPIO_DIR_OUT 0 +#define ARM_TF_GPIO_DIR_IN 1 + +#define ARM_TF_GPIO_LEVEL_LOW 0 +#define ARM_TF_GPIO_LEVEL_HIGH 1 + +#define ARM_TF_GPIO_PULL_NONE 0 +#define ARM_TF_GPIO_PULL_UP 1 +#define ARM_TF_GPIO_PULL_DOWN 2 + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H */ diff --git a/include/export/lib/bl_aux_params/bl_aux_params_exp.h b/include/export/lib/bl_aux_params/bl_aux_params_exp.h new file mode 100644 index 00000000..7391dec3 --- /dev/null +++ b/include/export/lib/bl_aux_params/bl_aux_params_exp.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../drivers/gpio_exp.h" + +/* + * This API implements a lightweight parameter passing mechanism that can be + * used to pass SoC Firmware configuration data from BL2 to BL31 by platforms or + * configurations that do not want to depend on libfdt. It is structured as a + * singly-linked list of parameter structures that all share the same common + * header but may have different (and differently-sized) structure bodies after + * that. The header contains a type field to indicate the parameter type (which + * is used to infer the structure length and how to interpret its contents) and + * a next pointer which contains the absolute physical address of the next + * parameter structure. The next pointer in the last structure block is set to + * NULL. The picture below shows how the parameters are kept in memory. + * + * head of list ---> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * +----| next | | + * | +----------------+ --+ + * | | parameter data | + * | +----------------+ + * | + * +--> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * NULL <---| next | | + * +----------------+ --+ + * | parameter data | + * +----------------+ + * + * Note: The SCTLR_EL3.A bit (Alignment fault check enable) is set in TF-A, so + * BL2 must ensure that each parameter struct starts on a 64-bit aligned address + * to avoid alignment faults. Parameters may be allocated in any address range + * accessible at the time of BL31 handoff (e.g. SRAM, DRAM, SoC-internal scratch + * registers, etc.), in particular address ranges that may not be mapped in + * BL31's page tables, so the parameter list must be parsed before the MMU is + * enabled and any information that is required at a later point should be + * deep-copied out into BL31-internal data structures. + */ + +enum bl_aux_param_type { + BL_AUX_PARAM_NONE = 0, + BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST = 0x1, + /* 0x1 - 0x7fffffff can be used by vendor-specific handlers. */ + BL_AUX_PARAM_VENDOR_SPECIFIC_LAST = 0x7fffffff, + BL_AUX_PARAM_GENERIC_FIRST = 0x80000001, + BL_AUX_PARAM_COREBOOT_TABLE = BL_AUX_PARAM_GENERIC_FIRST, + /* 0x80000001 - 0xffffffff are reserved for the generic handler. */ + BL_AUX_PARAM_GENERIC_LAST = 0xffffffff, + /* Top 32 bits of the type field are reserved for future use. */ +}; + +/* common header for all BL aux parameters */ +struct bl_aux_param_header { + uint64_t type; + uint64_t next; +}; + +/* commonly useful parameter structures that can be shared by multiple types */ +struct bl_aux_param_uint64 { + struct bl_aux_param_header h; + uint64_t value; +}; + +struct bl_aux_gpio_info { + uint8_t polarity; + uint8_t direction; + uint8_t pull_mode; + uint8_t reserved; + uint32_t index; +}; + +struct bl_aux_param_gpio { + struct bl_aux_param_header h; + struct bl_aux_gpio_info gpio; +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H */ diff --git a/include/export/lib/utils_def_exp.h b/include/export/lib/utils_def_exp.h new file mode 100644 index 00000000..86c409ce --- /dev/null +++ b/include/export/lib/utils_def_exp.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +/* + * For those constants to be shared between C and other sources, apply a 'U', + * 'UL', 'ULL', 'L' or 'LL' suffix to the argument only in C, to avoid + * undefined or unintended behaviour. + * + * The GNU assembler and linker do not support these suffixes (it causes the + * build process to fail) therefore the suffix is omitted when used in linker + * scripts and assembler files. +*/ +#if defined(__ASSEMBLER__) +# define U(_x) (_x) +# define UL(_x) (_x) +# define ULL(_x) (_x) +# define L(_x) (_x) +# define LL(_x) (_x) +#else +# define U(_x) (_x##U) +# define UL(_x) (_x##UL) +# define ULL(_x) (_x##ULL) +# define L(_x) (_x##L) +# define LL(_x) (_x##LL) +#endif + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H */ diff --git a/include/export/plat/rockchip/common/plat_params_exp.h b/include/export/plat/rockchip/common/plat_params_exp.h new file mode 100644 index 00000000..ccc9cd94 --- /dev/null +++ b/include/export/plat/rockchip/common/plat_params_exp.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../../lib/bl_aux_params/bl_aux_params_exp.h" + +/* param type */ +enum bl_aux_rk_param_type { + BL_AUX_PARAM_RK_RESET_GPIO = BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST, + BL_AUX_PARAM_RK_POWEROFF_GPIO, + BL_AUX_PARAM_RK_SUSPEND_GPIO, + BL_AUX_PARAM_RK_SUSPEND_APIO, +}; + +struct bl_aux_rk_apio_info { + uint8_t apio1 : 1; + uint8_t apio2 : 1; + uint8_t apio3 : 1; + uint8_t apio4 : 1; + uint8_t apio5 : 1; +}; + +struct bl_aux_param_rk_apio { + struct bl_aux_param_header h; + struct bl_aux_rk_apio_info apio; +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H */ diff --git a/include/lib/bl_aux_params/bl_aux_params.h b/include/lib/bl_aux_params/bl_aux_params.h new file mode 100644 index 00000000..f6ce8024 --- /dev/null +++ b/include/lib/bl_aux_params/bl_aux_params.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LIB_BL_AUX_PARAMS_H +#define LIB_BL_AUX_PARAMS_H + +#include <stdbool.h> +#include <stdint.h> + +#include <export/lib/bl_aux_params/bl_aux_params_exp.h> + +/* + * Handler function that handles an individual aux parameter. Return true if + * the parameter was handled, and flase if bl_aux_params_parse() should make its + * own attempt at handling it (for generic parameters). + */ +typedef bool (*bl_aux_param_handler_t)(struct bl_aux_param_header *param); + +/* + * Interprets head as the start of an aux parameter list, and passes the + * parameters individually to handler(). Handles generic parameters directly if + * handler() hasn't already done so. If only generic parameters are expected, + * handler() can be NULL. + */ +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler); + +#endif /* LIB_BL_AUX_PARAMS_H */ diff --git a/include/lib/cpus/aarch64/cortex_hercules.h b/include/lib/cpus/aarch64/cortex_hercules.h new file mode 100644 index 00000000..86e8af03 --- /dev/null +++ b/include/lib/cpus/aarch64/cortex_hercules.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_HERCULES_H +#define CORTEX_HERCULES_H + +#include <lib/utils_def.h> + +#define CORTEX_HERCULES_MIDR U(0x410FD410) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_HERCULES_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_HERCULES_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_HERCULES_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT U(1) + +#endif /* CORTEX_HERCULES_H */ diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h index 2b489675..41f71e84 100644 --- a/include/lib/utils_def.h +++ b/include/lib/utils_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,8 @@ #ifndef UTILS_DEF_H #define UTILS_DEF_H +#include <export/lib/utils_def_exp.h> + /* Compute the number of elements in the given array */ #define ARRAY_SIZE(a) \ (sizeof(a) / sizeof((a)[0])) @@ -106,29 +108,6 @@ #define check_u32_overflow(_u32, _inc) \ ((_u32) > (UINT32_MAX - (_inc))) -/* - * For those constants to be shared between C and other sources, apply a 'U', - * 'UL', 'ULL', 'L' or 'LL' suffix to the argument only in C, to avoid - * undefined or unintended behaviour. - * - * The GNU assembler and linker do not support these suffixes (it causes the - * build process to fail) therefore the suffix is omitted when used in linker - * scripts and assembler files. -*/ -#if defined(__LINKER__) || defined(__ASSEMBLY__) -# define U(_x) (_x) -# define UL(_x) (_x) -# define ULL(_x) (_x) -# define L(_x) (_x) -# define LL(_x) (_x) -#else -# define U(_x) (_x##U) -# define UL(_x) (_x##UL) -# define ULL(_x) (_x##ULL) -# define L(_x) (_x##L) -# define LL(_x) (_x##LL) -#endif - /* Register size of the current architecture. */ #ifdef AARCH32 #define REGSZ U(4) diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 97e67225..c8260e88 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -252,7 +252,7 @@ void plat_arm_interconnect_enter_coherency(void); void plat_arm_interconnect_exit_coherency(void); void plat_arm_program_trusted_mailbox(uintptr_t address); int plat_arm_bl1_fwu_needed(void); -void plat_arm_error_handler(int err); +__dead2 void plat_arm_error_handler(int err); #if ARM_PLAT_MT unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr); diff --git a/lib/bl_aux_params/bl_aux_params.c b/lib/bl_aux_params/bl_aux_params.c new file mode 100644 index 00000000..7a8115c6 --- /dev/null +++ b/lib/bl_aux_params/bl_aux_params.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <lib/coreboot.h> +#include <lib/bl_aux_params/bl_aux_params.h> + +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler) +{ + struct bl_aux_param_header *p; + + for (p = (void *)head; p; p = (void *)(uintptr_t)p->next) { + if (handler && handler(p)) + continue; + + switch (p->type) { +#if COREBOOT + case BL_AUX_PARAM_COREBOOT_TABLE: + coreboot_table_setup((void *)(uintptr_t) + ((struct bl_aux_param_uint64 *)p)->value); + break; +#endif + default: + ERROR("Ignoring unknown BL aux parameter: 0x%llx", + p->type); + break; + } + } +} diff --git a/lib/cpus/aarch64/cortex_hercules.S b/lib/cpus/aarch64/cortex_hercules.S new file mode 100644 index 00000000..25287de8 --- /dev/null +++ b/lib/cpus/aarch64/cortex_hercules.S @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <common/bl_common.h> +#include <cortex_hercules.h> +#include <cpu_macros.S> +#include <plat_macros.S> + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "cortex_hercules must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_hercules_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_HERCULES_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_HERCULES_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT + msr CORTEX_HERCULES_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_hercules_core_pwr_dwn + + /* + * Errata printing function for cortex_hercules. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_hercules_errata_report + ret +endfunc cortex_hercules_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_hercules specific + * register information for crash reporting. + * It needs to return with x6 pointing to + * a list of register names in ascii and + * x8 - x15 having values of registers to be + * reported. + * --------------------------------------------- + */ +.section .rodata.cortex_hercules_regs, "aS" +cortex_hercules_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_hercules_cpu_reg_dump + adr x6, cortex_hercules_regs + mrs x8, CORTEX_HERCULES_CPUECTLR_EL1 + ret +endfunc cortex_hercules_cpu_reg_dump + +declare_cpu_ops cortex_hercules, CORTEX_HERCULES_MIDR, \ + CPU_NO_RESET_FUNC, \ + cortex_hercules_core_pwr_dwn diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 89d7ed68..05ba5ed6 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -12,6 +12,7 @@ #include <arch.h> #include <arch_helpers.h> +#include <arch_features.h> #include <bl31/interrupt_mgmt.h> #include <common/bl_common.h> #include <context.h> @@ -136,6 +137,18 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) scr_el3 |= SCR_API_BIT | SCR_APK_BIT; #endif /* !CTX_INCLUDE_PAUTH_REGS */ + unsigned int mte = get_armv8_5_mte_support(); + + /* + * Enable MTE support unilaterally for normal world if the CPU supports + * it. + */ + if (mte != MTE_UNIMPLEMENTED) { + if (security_state == NON_SECURE) { + scr_el3 |= SCR_ATA_BIT; + } + } + #ifdef IMAGE_BL31 /* * SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ routing as diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile index bc05d0fa..60c14580 100644 --- a/lib/romlib/Makefile +++ b/lib/romlib/Makefile @@ -5,9 +5,11 @@ # AS = $(CROSS_COMPILE)as +AR = $(CROSS_COMPILE)ar LD = $(CROSS_COMPILE)ld OC = $(CROSS_COMPILE)objcopy CPP = $(CROSS_COMPILE)cpp +ROMLIB_GEN = ./romlib_generator.py BUILD_DIR = ../../$(BUILD_PLAT)/romlib LIB_DIR = ../../$(BUILD_PLAT)/lib WRAPPER_DIR = ../../$(BUILD_PLAT)/libwrapper @@ -17,6 +19,11 @@ PPFLAGS = $(INC) $(DEFINES) -P -D__ASSEMBLY__ -D__LINKER__ -MD -MP -MT $(BUI OBJS = $(BUILD_DIR)/jmptbl.o $(BUILD_DIR)/init.o MAPFILE = ../../$(BUILD_PLAT)/romlib/romlib.map +ifneq ($(PLAT_DIR),) + WRAPPER_SOURCES = $(shell $(ROMLIB_GEN) genwrappers -b $(WRAPPER_DIR) --list ../../$(PLAT_DIR)/jmptbl.i) + WRAPPER_OBJS = $(WRAPPER_SOURCES:.s=.o) +endif + V ?= 0 ifeq ($(V),0) Q := @ @@ -61,19 +68,31 @@ $(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf $(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf @echo " VAR $@" - $(Q)./genvar.sh -o $@ $(BUILD_DIR)/romlib.elf + $(Q)$(ROMLIB_GEN) genvar --output $@ $< -$(LIB_DIR)/libwrappers.a: $(BUILD_DIR)/jmptbl.i $(WRAPPER_DIR)/jmpvar.o +$(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) @echo " AR $@" - $(Q)./genwrappers.sh -b $(WRAPPER_DIR) -o $@ --bti=$(ENABLE_BTI) --asflags=$(ASFLAGS) $(BUILD_DIR)/jmptbl.i + $(Q)$(AR) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) + +$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i + @echo " PRE $@" + $(Q)$(ROMLIB_GEN) pre --output $@ --deps $(BUILD_DIR)/jmptbl.d $< + +$(BUILD_DIR)/wrappers.stamp: $(BUILD_DIR)/jmptbl.i + @echo " WRP $<" + $(Q)$(ROMLIB_GEN) genwrappers --bti=$(ENABLE_BTI) -b $(WRAPPER_DIR) $< + @touch $@ + +$(WRAPPER_SOURCES): $(BUILD_DIR)/wrappers.stamp -$(BUILD_DIR)/jmptbl.i: $(BUILD_DIR)/jmptbl.s +$(WRAPPER_OBJS): $(WRAPPER_SOURCES) $(BUILD_DIR)/wrappers.stamp -$(BUILD_DIR)/jmptbl.s: ../../$(PLAT_DIR)/jmptbl.i +$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i @echo " TBL $@" - $(Q)./gentbl.sh -o $@ -b $(BUILD_DIR) --bti=$(ENABLE_BTI) ../../$(PLAT_DIR)/jmptbl.i + $(Q)$(ROMLIB_GEN) gentbl --output $@ --bti=$(ENABLE_BTI) $< clean: @rm -f $(BUILD_DIR)/* -include $(BUILD_DIR)/romlib.d +-include $(BUILD_DIR)/jmptbl.d diff --git a/lib/romlib/gentbl.sh b/lib/romlib/gentbl.sh deleted file mode 100755 index bfb1ec3cf..00000000 --- a/lib/romlib/gentbl.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause - -set -e - -output=jmptbl.s -build=. - -for i -do - case $i in - -o) - output=$2 - shift 2 - ;; - -b) - build=$2 - shift 2 - ;; - --bti=*) - enable_bti=$(echo $1 | sed 's/--bti=\(.*\)/\1/') - shift 1 - ;; - --) - shift - break - ;; - -*) - echo usage: gentbl.sh [-o output] [-b dir] file ... >&2 - exit 1 - ;; - esac -done - -tmp=`mktemp` -trap "rm -f $$.tmp" EXIT INT QUIT -rm -f $output - -# Pre-process include files -awk '!/^$/ && !/[:blank:]*#.*/{ -if (NF == 2 && $1 == "include") { - while ((getline line < $2) > 0) - if (line !~ /^$/ && line !~ /[:blank:]*#.*/) - print line - close($2) -} else - print -}' "$@" | -awk -v OFS="\t" ' -BEGIN{print "#index\tlib\tfunction\t[patch]"} -{print NR-1, $0}' | tee $build/jmptbl.i | -awk -v OFS="\n" -v BTI=$enable_bti ' -BEGIN {print "\t.text", - "\t.globl\tjmptbl", - "jmptbl:"} - {sub(/[:blank:]*#.*/,"")} -!/^$/ { - if (BTI == 1) - print "\tbti\tj" - if ($3 == "reserved") - print "\t.word\t0x0" - else - print "\tb\t" $3}' > $$.tmp && -mv $$.tmp $output diff --git a/lib/romlib/genvar.sh b/lib/romlib/genvar.sh deleted file mode 100755 index a3e2cdf6..00000000 --- a/lib/romlib/genvar.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause - -set -e - -output=jmpvar.s -for i -do - case $i in - -o) - output=$2 - shift 2 - ;; - --) - shift - break - ;; - -*) - echo usage: genvar.sh [-o output] file... >&2 - ;; - esac -done - -tmp=`mktemp` -trap "rm -f $tmp" EXIT INT QUIT - -nm -a "$@" | -awk -v OFS="\n" ' -$3 == ".text" {print "\t.data", - "\t.globl\tjmptbl", - "\t.align\t4", - "jmptbl:\t.quad\t0x" $1}' > $tmp - -mv $tmp $output diff --git a/lib/romlib/genwrappers.sh b/lib/romlib/genwrappers.sh deleted file mode 100755 index e092548e..00000000 --- a/lib/romlib/genwrappers.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh -# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause - -set -e - -build=. -out=output.a - -for i -do - case $i in - -o) - out=$2 - shift 2 - ;; - -b) - build=$2 - shift 2 - ;; - --bti=*) - enable_bti=$(echo $1 | sed 's/--bti=\(.*\)/\1/') - shift 1 - ;; - --asflags=*) - asflags=$(echo $1 | sed 's/--asflags=\(.*\)/\1/') - shift 1 - ;; - --) - shift - break - ;; - -*) - echo usage: genwrappers.sh [-o output] [-b dir] file ... >&2 - exit 1 - ;; - esac -done - -awk -v BTI=$enable_bti ' -{sub(/[:blank:]*#.*/,"")} -!/^$/ && $NF != "patch" && $NF != "reserved" { - if (BTI == 1) - print $1*8, $2, $3 - else - print $1*4, $2, $3}' "$@" | -while read idx lib sym -do - file=$build/${lib}_$sym - - cat <<EOF > $file.s - .globl $sym -$sym: -EOF -if [ $enable_bti = 1 ] -then - echo "\tbti\tjc" >> $file.s -fi - cat <<EOF >> $file.s - ldr x17, =jmptbl - mov x16, #$idx - ldr x17, [x17] - add x16, x16, x17 - br x16 -EOF - - ${CROSS_COMPILE}as ${asflags} -o $file.o $file.s -done - -${CROSS_COMPILE}ar -rc $out $build/*.o diff --git a/lib/romlib/romlib_generator.py b/lib/romlib/romlib_generator.py new file mode 100755 index 00000000..0682dd49 --- /dev/null +++ b/lib/romlib/romlib_generator.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +""" +This module contains a set of classes and a runner that can generate code for the romlib module +based on the templates in the 'templates' directory. +""" + +import argparse +import os +import re +import subprocess +import string +import sys + +class IndexFileParser: + """ + Parses the contents of the index file into the items and dependencies variables. It + also resolves included files in the index files recursively with circular inclusion detection. + """ + + def __init__(self): + self.items = [] + self.dependencies = {} + self.include_chain = [] + + def add_dependency(self, parent, dependency): + """ Adds a dependency into the dependencies variable. """ + if parent in self.dependencies: + self.dependencies[parent].append(dependency) + else: + self.dependencies[parent] = [dependency] + + def get_dependencies(self, parent): + """ Gets all the recursive dependencies of a parent file. """ + parent = os.path.normpath(parent) + if parent in self.dependencies: + direct_deps = self.dependencies[parent] + deps = direct_deps + for direct_dep in direct_deps: + deps += self.get_dependencies(direct_dep) + return deps + + return [] + + def parse(self, file_name): + """ Opens and parses index file. """ + file_name = os.path.normpath(file_name) + + if file_name not in self.include_chain: + self.include_chain.append(file_name) + self.dependencies[file_name] = [] + else: + raise Exception("Circular dependency detected: " + file_name) + + with open(file_name, "r") as index_file: + for line in index_file.readlines(): + line_elements = line.split() + + if line.startswith("#") or not line_elements: + # Comment or empty line + continue + + if line_elements[0] == "reserved": + # Reserved slot in the jump table + self.items.append({"type": "reserved"}) + elif line_elements[0] == "include" and len(line_elements) > 1: + # Include other index file + included_file = os.path.normpath(line_elements[1]) + self.add_dependency(file_name, included_file) + self.parse(included_file) + elif len(line_elements) > 1: + # Library function + library_name = line_elements[0] + function_name = line_elements[1] + patch = bool(len(line_elements) > 2 and line_elements[2] == "patch") + + self.items.append({"type": "function", "library_name": library_name, + "function_name": function_name, "patch": patch}) + else: + raise Exception("Invalid line: '" + line + "'") + + self.include_chain.pop() + +class RomlibApplication: + """ Base class of romlib applications. """ + TEMPLATE_DIR = os.path.dirname(os.path.realpath(__file__)) + "/templates/" + + def __init__(self, prog): + self.args = argparse.ArgumentParser(prog=prog, description=self.__doc__) + self.config = None + + def parse_arguments(self, argv): + """ Parses the arguments that should come from the command line arguments. """ + self.config = self.args.parse_args(argv) + + def build_template(self, name, mapping=None, remove_comment=False): + """ + Loads a template and builds it with the defined mapping. Template paths are always relative + to this script. + """ + + with open(self.TEMPLATE_DIR + name, "r") as template_file: + if remove_comment: + # Removing copyright comment to make the generated code more readable when the + # template is inserted multiple times into the output. + template_lines = template_file.readlines() + end_of_comment_line = 0 + for index, line in enumerate(template_lines): + if line.find("*/") != -1: + end_of_comment_line = index + break + template_data = "".join(template_lines[end_of_comment_line + 1:]) + else: + template_data = template_file.read() + + template = string.Template(template_data) + return template.substitute(mapping) + +class IndexPreprocessor(RomlibApplication): + """ Removes empty and comment lines from the index file and resolves includes. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("--deps", help="Dependency file") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + After parsing the input index file it generates a clean output with all includes resolved. + Using --deps option it also outputs the dependencies in makefile format like gcc's with -M. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + with open(self.config.output, "w") as output_file: + for item in index_file_parser.items: + if item["type"] == "function": + patch = "\tpatch" if item["patch"] else "" + output_file.write( + item["library_name"] + "\t" + item["function_name"] + patch + "\n") + else: + output_file.write("reserved\n") + + if self.config.deps: + with open(self.config.deps, "w") as deps_file: + deps = [self.config.file] + index_file_parser.get_dependencies(self.config.file) + deps_file.write(self.config.output + ": " + " \\\n".join(deps) + "\n") + +class TableGenerator(RomlibApplication): + """ Generates the jump table by parsing the index file. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("--bti", help="Branch Target Identification", type=int) + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Inserts the jmptbl definition and the jump entries into the output file. Also can insert + BTI related code before entries if --bti option set. It can output a dependency file of the + included index files. This can be directly included in makefiles. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + with open(self.config.output, "w") as output_file: + output_file.write(self.build_template("jmptbl_header.S")) + bti = "_bti" if self.config.bti == 1 else "" + + for item in index_file_parser.items: + template_name = "jmptbl_entry_" + item["type"] + bti + ".S" + output_file.write(self.build_template(template_name, item, True)) + +class WrapperGenerator(RomlibApplication): + """ + Generates a wrapper function for each entry in the index file except for the ones that contain + the keyword patch. The generated wrapper file is called <lib>_<fn_name>.s. + """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-b", help="Build directory", default=".", metavar="build") + self.args.add_argument("--bti", help="Branch Target Identification", type=int) + self.args.add_argument("--list", help="Only list assembly files", action="store_true") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Iterates through the items in the parsed index file and builds the template for each entry. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + bti = "_bti" if self.config.bti == 1 else "" + function_offset = 0 + files = [] + + for item_index in range(0, len(index_file_parser.items)): + item = index_file_parser.items[item_index] + + if item["type"] == "reserved" or item["patch"]: + continue + + asm = self.config.b + "/" + item["function_name"] + ".s" + if self.config.list: + # Only listing files + files.append(asm) + else: + with open(asm, "w") as asm_file: + # The jump instruction is 4 bytes but BTI requires and extra instruction so + # this makes it 8 bytes per entry. + function_offset = item_index * (8 if self.config.bti else 4) + + item["function_offset"] = function_offset + asm_file.write(self.build_template("wrapper" + bti + ".S", item)) + + if self.config.list: + print(" ".join(files)) + +class VariableGenerator(RomlibApplication): + """ Generates the jump table global variable with the absolute address in ROM. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Runs nm -a command on the input file and inserts the address of the .text section into the + template as the ROM address of the jmp_table. + """ + symbols = subprocess.check_output(["nm", "-a", self.config.file]) + + matching_symbol = re.search("([0-9A-Fa-f]+) . \\.text", str(symbols)) + if not matching_symbol: + raise Exception("No '.text' section was found in %s" % self.config.file) + + mapping = {"jmptbl_address": matching_symbol.group(1)} + + with open(self.config.output, "w") as output_file: + output_file.write(self.build_template("jmptbl_glob_var.S", mapping)) + +if __name__ == "__main__": + APPS = {"genvar": VariableGenerator, "pre": IndexPreprocessor, + "gentbl": TableGenerator, "genwrappers": WrapperGenerator} + + if len(sys.argv) < 2 or sys.argv[1] not in APPS: + print("usage: romlib_generator.py [%s] [args]" % "|".join(APPS.keys()), file=sys.stderr) + sys.exit(1) + + APP = APPS[sys.argv[1]]("romlib_generator.py " + sys.argv[1]) + APP.parse_arguments(sys.argv[2:]) + try: + APP.main() + sys.exit(0) + except FileNotFoundError as file_not_found_error: + print(file_not_found_error, file=sys.stderr) + except subprocess.CalledProcessError as called_process_error: + print(called_process_error.output, file=sys.stderr) + + sys.exit(1) diff --git a/lib/romlib/templates/jmptbl_entry_function.S b/lib/romlib/templates/jmptbl_entry_function.S new file mode 100644 index 00000000..a0f84561 --- /dev/null +++ b/lib/romlib/templates/jmptbl_entry_function.S @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + b ${function_name} diff --git a/lib/romlib/templates/jmptbl_entry_function_bti.S b/lib/romlib/templates/jmptbl_entry_function_bti.S new file mode 100644 index 00000000..d96ee94d --- /dev/null +++ b/lib/romlib/templates/jmptbl_entry_function_bti.S @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + bti j + b ${function_name} diff --git a/lib/romlib/templates/jmptbl_entry_reserved.S b/lib/romlib/templates/jmptbl_entry_reserved.S new file mode 100644 index 00000000..a9b5f181 --- /dev/null +++ b/lib/romlib/templates/jmptbl_entry_reserved.S @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + b . diff --git a/lib/romlib/templates/jmptbl_entry_reserved_bti.S b/lib/romlib/templates/jmptbl_entry_reserved_bti.S new file mode 100644 index 00000000..a9f03759 --- /dev/null +++ b/lib/romlib/templates/jmptbl_entry_reserved_bti.S @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + bti j + b . diff --git a/lib/romlib/templates/jmptbl_glob_var.S b/lib/romlib/templates/jmptbl_glob_var.S new file mode 100644 index 00000000..d3065125 --- /dev/null +++ b/lib/romlib/templates/jmptbl_glob_var.S @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .data + .globl jmptbl + .align 4 +jmptbl: .quad 0x${jmptbl_address} diff --git a/lib/romlib/templates/jmptbl_header.S b/lib/romlib/templates/jmptbl_header.S new file mode 100644 index 00000000..72b8ce54 --- /dev/null +++ b/lib/romlib/templates/jmptbl_header.S @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .text + .globl jmptbl +jmptbl: diff --git a/lib/romlib/templates/wrapper.S b/lib/romlib/templates/wrapper.S new file mode 100644 index 00000000..734a68a2 --- /dev/null +++ b/lib/romlib/templates/wrapper.S @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .globl ${function_name} +${function_name}: + ldr x17, =jmptbl + mov x16, #${function_offset} + ldr x17, [x17] + add x16, x16, x17 + br x16 diff --git a/lib/romlib/templates/wrapper_bti.S b/lib/romlib/templates/wrapper_bti.S new file mode 100644 index 00000000..ba9b11ce --- /dev/null +++ b/lib/romlib/templates/wrapper_bti.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .globl ${function_name} +${function_name}: + bti jc + ldr x17, =jmptbl + mov x16, #${function_offset} + ldr x17, [x17] + add x16, x16, x17 + br x16 diff --git a/plat/arm/board/a5ds/a5ds_err.c b/plat/arm/board/a5ds/a5ds_err.c new file mode 100644 index 00000000..65b41dd4 --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * a5ds error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk index 4fd357b8..d42b2bfa 100644 --- a/plat/arm/board/a5ds/platform.mk +++ b/plat/arm/board/a5ds/platform.mk @@ -36,6 +36,7 @@ BL1_SOURCES += drivers/io/io_fip.c \ drivers/cfi/v2m/v2m_flash.c \ plat/arm/common/arm_bl1_setup.c \ plat/arm/common/arm_err.c \ + plat/arm/board/a5ds/a5ds_err.c \ plat/arm/common/arm_io_storage.c \ plat/arm/board/a5ds/${ARCH}/a5ds_helpers.S \ plat/arm/board/a5ds/a5ds_bl1_setup.c \ @@ -55,6 +56,7 @@ BL2_SOURCES += lib/aarch32/arm32_aeabi_divmod.c \ plat/arm/board/a5ds/a5ds_bl2_setup.c \ plat/arm/common/arm_bl2_setup.c \ plat/arm/common/arm_err.c \ + plat/arm/board/a5ds/a5ds_err.c \ plat/arm/common/arm_io_storage.c \ plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \ plat/arm/common/arm_image_load.c \ diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c index 420df455..b90ddcd3 100644 --- a/plat/arm/board/fvp/fvp_bl1_setup.c +++ b/plat/arm/board/fvp/fvp_bl1_setup.c @@ -52,3 +52,12 @@ void bl1_platform_setup(void) if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) smmuv3_security_init(PLAT_FVP_SMMUV3_BASE); } + +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (1) + wfi(); +} diff --git a/plat/arm/board/fvp/fvp_err.c b/plat/arm/board/fvp/fvp_err.c new file mode 100644 index 00000000..2437cd47 --- /dev/null +++ b/plat/arm/board/fvp/fvp_err.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> + +#include <common/debug.h> +#include <drivers/arm/sp805.h> +#include <drivers/cfi/v2m_flash.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +/* + * FVP error handler + */ +__dead2 void plat_arm_error_handler(int err) +{ + int ret; + + switch (err) { + case -ENOENT: + case -EAUTH: + /* Image load or authentication error. Erase the ToC */ + INFO("Erasing FIP ToC from flash...\n"); + (void)nor_unlock(PLAT_ARM_FIP_BASE); + ret = nor_word_program(PLAT_ARM_FIP_BASE, 0); + if (ret != 0) { + ERROR("Cannot erase ToC\n"); + } else { + INFO("Done\n"); + } + break; + default: + /* Unexpected error */ + break; + } + + (void)console_flush(); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + for (;;) + wfi(); +} diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index bd6812b7..0eb62c44 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -112,7 +112,8 @@ else lib/cpus/aarch64/cortex_a77.S \ lib/cpus/aarch64/neoverse_n1.S \ lib/cpus/aarch64/neoverse_e1.S \ - lib/cpus/aarch64/neoverse_zeus.S + lib/cpus/aarch64/neoverse_zeus.S \ + lib/cpus/aarch64/cortex_hercules.S # AArch64/AArch32 else FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \ @@ -131,17 +132,20 @@ BL1_SOURCES += drivers/arm/smmu/smmu_v3.c \ lib/semihosting/${ARCH}/semihosting_call.S \ plat/arm/board/fvp/${ARCH}/fvp_helpers.S \ plat/arm/board/fvp/fvp_bl1_setup.c \ + plat/arm/board/fvp/fvp_err.c \ plat/arm/board/fvp/fvp_io_storage.c \ plat/arm/board/fvp/fvp_trusted_boot.c \ ${FVP_CPU_LIBS} \ ${FVP_INTERCONNECT_SOURCES} -BL2_SOURCES += drivers/io/io_semihosting.c \ +BL2_SOURCES += drivers/arm/sp805/sp805.c \ + drivers/io/io_semihosting.c \ lib/utils/mem_region.c \ lib/semihosting/semihosting.c \ lib/semihosting/${ARCH}/semihosting_call.S \ plat/arm/board/fvp/fvp_bl2_setup.c \ + plat/arm/board/fvp/fvp_err.c \ plat/arm/board/fvp/fvp_io_storage.c \ plat/arm/board/fvp/fvp_trusted_boot.c \ plat/arm/common/arm_nor_psci_mem_protect.c \ diff --git a/plat/arm/board/fvp_ve/fvp_ve_err.c b/plat/arm/board/fvp_ve/fvp_ve_err.c new file mode 100644 index 00000000..7f9d2f7e --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * FVP VE error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk index f85452da..4d21f4ba 100644 --- a/plat/arm/board/fvp_ve/platform.mk +++ b/plat/arm/board/fvp_ve/platform.mk @@ -40,6 +40,7 @@ BL1_SOURCES += drivers/arm/sp805/sp805.c \ drivers/io/io_storage.c \ plat/arm/common/arm_bl1_setup.c \ plat/arm/common/arm_err.c \ + plat/arm/board/fvp_ve/fvp_ve_err.c \ plat/arm/common/arm_io_storage.c \ drivers/cfi/v2m/v2m_flash.c \ plat/arm/board/fvp_ve/${ARCH}/fvp_ve_helpers.S \ @@ -60,6 +61,7 @@ BL2_SOURCES += plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c \ drivers/io/io_storage.c \ plat/arm/common/arm_bl2_setup.c \ plat/arm/common/arm_err.c \ + plat/arm/board/fvp_ve/fvp_ve_err.c \ plat/arm/common/arm_io_storage.c \ plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \ plat/arm/common/arm_image_load.c \ diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c index 7a3d22de..89398d68 100644 --- a/plat/arm/board/juno/juno_bl1_setup.c +++ b/plat/arm/board/juno/juno_bl1_setup.c @@ -98,6 +98,9 @@ __dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) /* Clear the NV flags register. */ *nv_flags_clr = *nv_flags_ptr; + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + while (1) wfi(); } diff --git a/plat/arm/board/juno/juno_err.c b/plat/arm/board/juno/juno_err.c index 700b96cb..961bfda1 100644 --- a/plat/arm/board/juno/juno_err.c +++ b/plat/arm/board/juno/juno_err.c @@ -7,6 +7,7 @@ #include <errno.h> #include <arch_helpers.h> +#include <drivers/arm/sp805.h> #include <plat/arm/common/plat_arm.h> #include <plat/common/platform.h> #include <platform_def.h> @@ -21,7 +22,9 @@ void __dead2 plat_arm_error_handler(int err) /* Propagate the err code in the NV-flags register */ *flags_ptr = err; - /* Loop until the watchdog resets the system */ + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + for (;;) wfi(); } diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 40e62644..ea7f8517 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -66,7 +66,8 @@ BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \ ${JUNO_INTERCONNECT_SOURCES} \ ${JUNO_SECURITY_SOURCES} -BL2_SOURCES += lib/utils/mem_region.c \ +BL2_SOURCES += drivers/arm/sp805/sp805.c \ + lib/utils/mem_region.c \ plat/arm/board/juno/juno_err.c \ plat/arm/board/juno/juno_bl2_setup.c \ plat/arm/common/arm_nor_psci_mem_protect.c \ diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c index a831b89f..632af7b4 100644 --- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c +++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c @@ -80,8 +80,17 @@ void dmc_ecc_setup(uint32_t ddr_size_gb) flush_dcache_range(ARM_DRAM2_BASE, dram2_size); INFO("Enabling ECC on DMCs\n"); + /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ + mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); + mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); + + /* Enable ECC in DMCs */ mmio_setbits_32(N1SDP_DMC0_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); mmio_setbits_32(N1SDP_DMC1_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); + + /* Set DMCs to READY state */ + mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); + mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); } void copy_bl33(uint32_t src, uint32_t dst, uint32_t size) diff --git a/plat/arm/board/n1sdp/n1sdp_def.h b/plat/arm/board/n1sdp/n1sdp_def.h index b7f7213d..d43c5a47 100644 --- a/plat/arm/board/n1sdp/n1sdp_def.h +++ b/plat/arm/board/n1sdp/n1sdp_def.h @@ -25,10 +25,18 @@ #define N1SDP_SDS_BL33_INFO_OFFSET 0 #define N1SDP_SDS_BL33_INFO_SIZE 12 +/* DMC memory command registers */ +#define N1SDP_DMC0_MEMC_CMD_REG 0x4E000008 +#define N1SDP_DMC1_MEMC_CMD_REG 0x4E100008 + /* DMC ERR0CTLR0 registers */ #define N1SDP_DMC0_ERR0CTLR0_REG 0x4E000708 #define N1SDP_DMC1_ERR0CTLR0_REG 0x4E100708 +/* DMC memory commands */ +#define N1SDP_DMC_MEMC_CMD_CONFIG 0 +#define N1SDP_DMC_MEMC_CMD_READY 3 + /* DMC ECC enable bit in ERR0CTLR0 register */ #define N1SDP_DMC_ERR0CTLR0_ECC_EN 0x1 diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk index 833bb821..db41e0ed 100644 --- a/plat/arm/board/rde1edge/platform.mk +++ b/plat/arm/board/rde1edge/platform.mk @@ -12,10 +12,12 @@ PLAT_INCLUDES += -I${RDE1EDGE_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_e1.S -BL1_SOURCES += ${SGI_CPU_SOURCES} +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDE1EDGE_BASE}/rde1edge_err.c BL2_SOURCES += ${RDE1EDGE_BASE}/rde1edge_plat.c \ ${RDE1EDGE_BASE}/rde1edge_security.c \ + ${RDE1EDGE_BASE}/rde1edge_err.c \ drivers/arm/tzc/tzc_dmc620.c \ lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c diff --git a/plat/arm/board/rde1edge/rde1edge_err.c b/plat/arm/board/rde1edge/rde1edge_err.c new file mode 100644 index 00000000..e344d826 --- /dev/null +++ b/plat/arm/board/rde1edge/rde1edge_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rde1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk index cacdaa13..b44c70a3 100644 --- a/plat/arm/board/rdn1edge/platform.mk +++ b/plat/arm/board/rdn1edge/platform.mk @@ -12,10 +12,12 @@ PLAT_INCLUDES += -I${RDN1EDGE_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S -BL1_SOURCES += ${SGI_CPU_SOURCES} +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN1EDGE_BASE}/rdn1edge_err.c BL2_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_plat.c \ ${RDN1EDGE_BASE}/rdn1edge_security.c \ + ${RDN1EDGE_BASE}/rdn1edge_err.c \ drivers/arm/tzc/tzc_dmc620.c \ lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c diff --git a/plat/arm/board/rdn1edge/rdn1edge_err.c b/plat/arm/board/rdn1edge/rdn1edge_err.c new file mode 100644 index 00000000..cdcbf256 --- /dev/null +++ b/plat/arm/board/rdn1edge/rdn1edge_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rdn1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk index e72225d3..b9fa0995 100644 --- a/plat/arm/board/sgi575/platform.mk +++ b/plat/arm/board/sgi575/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -12,10 +12,12 @@ PLAT_INCLUDES += -I${SGI575_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S -BL1_SOURCES += ${SGI_CPU_SOURCES} +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${SGI575_BASE}/sgi575_err.c BL2_SOURCES += ${SGI575_BASE}/sgi575_plat.c \ ${SGI575_BASE}/sgi575_security.c \ + ${SGI575_BASE}/sgi575_err.c \ drivers/arm/tzc/tzc_dmc620.c \ lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c diff --git a/plat/arm/board/sgi575/sgi575_err.c b/plat/arm/board/sgi575/sgi575_err.c new file mode 100644 index 00000000..c1cc1a7f --- /dev/null +++ b/plat/arm/board/sgi575/sgi575_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * sgi575 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/sgm775/platform.mk b/plat/arm/board/sgm775/platform.mk index c8337554..7a843c36 100644 --- a/plat/arm/board/sgm775/platform.mk +++ b/plat/arm/board/sgm775/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -12,7 +12,10 @@ FDT_SOURCES += ${SGM775_BASE}/fdts/sgm775_tb_fw_config.dts PLAT_INCLUDES +=-I${SGM775_BASE}/include/ +BL1_SOURCES += ${SGM775_BASE}/sgm775_err.c + BL2_SOURCES += lib/utils/mem_region.c \ + ${SGM775_BASE}/sgm775_err.c \ plat/arm/common/arm_nor_psci_mem_protect.c BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ diff --git a/plat/arm/board/sgm775/sgm775_err.c b/plat/arm/board/sgm775/sgm775_err.c new file mode 100644 index 00000000..e1e05860 --- /dev/null +++ b/plat/arm/board/sgm775/sgm775_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * sgm775 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/common/arm_err.c b/plat/arm/common/arm_err.c index e77f5dc5..f80ba78c 100644 --- a/plat/arm/common/arm_err.c +++ b/plat/arm/common/arm_err.c @@ -1,55 +1,14 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <errno.h> -#include <stdint.h> -#include <platform_def.h> - -#include <arch_helpers.h> -#include <common/debug.h> -#include <drivers/cfi/v2m_flash.h> -#include <drivers/console.h> #include <plat/arm/common/plat_arm.h> #include <plat/common/platform.h> -#pragma weak plat_arm_error_handler - -/* - * ARM common implementation for error handler - */ -void __dead2 plat_arm_error_handler(int err) -{ - int ret; - - switch (err) { - case -ENOENT: - case -EAUTH: - /* Image load or authentication error. Erase the ToC */ - INFO("Erasing FIP ToC from flash...\n"); - (void)nor_unlock(PLAT_ARM_FIP_BASE); - ret = nor_word_program(PLAT_ARM_FIP_BASE, 0); - if (ret != 0) { - ERROR("Cannot erase ToC\n"); - } else { - INFO("Done\n"); - } - break; - default: - /* Unexpected error */ - break; - } - - (void)console_flush(); - - /* Loop until the watchdog resets the system */ - for (;;) - wfi(); -} - void __dead2 plat_error_handler(int err) { plat_arm_error_handler(err); diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c index f81078f0..981ef376 100644 --- a/plat/hisilicon/poplar/bl31_plat_setup.c +++ b/plat/hisilicon/poplar/bl31_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -130,6 +130,6 @@ void bl31_plat_arch_setup(void) BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); - INFO("Boot BL33 from 0x%lx for %lu Bytes\n", + INFO("Boot BL33 from 0x%lx for %llu Bytes\n", bl33_image_ep_info.pc, bl33_image_ep_info.args.arg2); } diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c index 63d9223a..c3cd0d0c 100644 --- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c +++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c @@ -24,6 +24,7 @@ #include <gpc.h> #include <imx_aipstz.h> #include <imx_uart.h> +#include <imx_rdc.h> #include <imx8m_caam.h> #include <plat_imx8.h> @@ -41,6 +42,18 @@ static const struct aipstz_cfg aipstz[] = { {0}, }; +static const struct imx_rdc_cfg rdc[] = { + /* Master domain assignment */ + RDC_MDAn(0x1, DID1), + + /* peripherals domain permission */ + + /* memory region */ + + /* Sentinel */ + {0}, +}; + static entry_point_info_t bl32_image_ep_info; static entry_point_info_t bl33_image_ep_info; @@ -94,6 +107,8 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, imx_aipstz_init(aipstz); + imx_rdc_init(rdc); + imx8m_caam_init(); console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk index c28463b7..6d32dbba 100644 --- a/plat/imx/imx8m/imx8mm/platform.mk +++ b/plat/imx/imx8m/imx8mm/platform.mk @@ -20,6 +20,7 @@ IMX_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \ BL31_SOURCES += plat/imx/common/imx8_helpers.S \ plat/imx/imx8m/gpc_common.c \ plat/imx/imx8m/imx_aipstz.c \ + plat/imx/imx8m/imx_rdc.c \ plat/imx/imx8m/imx8m_caam.c \ plat/imx/imx8m/imx8m_psci_common.c \ plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c \ diff --git a/plat/imx/imx8m/imx_rdc.c b/plat/imx/imx8m/imx_rdc.c new file mode 100644 index 00000000..85de1911 --- /dev/null +++ b/plat/imx/imx8m/imx_rdc.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/mmio.h> + +#include <imx_rdc.h> + +void imx_rdc_init(const struct imx_rdc_cfg *rdc_cfg) +{ + const struct imx_rdc_cfg *rdc = rdc_cfg; + + while (rdc->type != RDC_INVALID) { + switch (rdc->type) { + case RDC_MDA: + /* MDA config */ + mmio_write_32(MDAn(rdc->index), rdc->setting.rdc_mda); + break; + case RDC_PDAP: + /* peripheral access permission config */ + mmio_write_32(PDAPn(rdc->index), rdc->setting.rdc_pdap); + break; + case RDC_MEM_REGION: + /* memory region access permission config */ + mmio_write_32(MRSAn(rdc->index), rdc->setting.rdc_mem_region[0]); + mmio_write_32(MREAn(rdc->index), rdc->setting.rdc_mem_region[1]); + mmio_write_32(MRCn(rdc->index), rdc->setting.rdc_mem_region[2]); + break; + default: + break; + } + + rdc++; + } +} diff --git a/plat/imx/imx8m/include/imx_rdc.h b/plat/imx/imx8m/include/imx_rdc.h new file mode 100644 index 00000000..6be8550d --- /dev/null +++ b/plat/imx/imx8m/include/imx_rdc.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_RDC_H +#define IMX_RDC_H + +#include <lib/utils_def.h> + +#include <platform_def.h> + +#define MDAn(x) (IMX_RDC_BASE + 0x200 + (x) * 4) +#define PDAPn(x) (IMX_RDC_BASE + 0x400 + (x) * 4) +#define MRSAn(x) (IMX_RDC_BASE + 0x800 + (x) * 4) +#define MREAn(x) (IMX_RDC_BASE + 0x804 + (x) * 4) +#define MRCn(x) (IMX_RDC_BASE + 0x808 + (x) * 4) + +#define LCK BIT(31) +#define SREQ BIT(30) +#define ENA BIT(30) + +#define DID0 U(0x0) +#define DID1 U(0x1) +#define DID2 U(0x2) +#define DID3 U(0x3) + +#define D3R BIT(7) +#define D3W BIT(6) +#define D2R BIT(5) +#define D2W BIT(4) +#define D1R BIT(3) +#define D1W BIT(2) +#define D0R BIT(1) +#define D0W BIT(0) + +union rdc_setting { + uint32_t rdc_mda; /* Master Domain Assignment */ + uint32_t rdc_pdap; /* Peripheral Domain Access Permissions */ + uint32_t rdc_mem_region[3]; /* Memory Region Access Control */ +}; + +enum rdc_type { + RDC_INVALID, + RDC_MDA, + RDC_PDAP, + RDC_MEM_REGION, +}; + +struct imx_rdc_cfg { + enum rdc_type type; /* config type Master, Peripheral or Memory region */ + int index; + union rdc_setting setting; +}; + +#define RDC_MDAn(i, mda) \ + {RDC_MDA, (i), .setting.rdc_mda = (mda), } +#define RDC_PDAPn(i, pdap) \ + {RDC_PDAP, (i), .setting.rdc_pdap = (pdap), } + +#define RDC_MEM_REGIONn(i, msa, mea, mrc) \ + { RDC_MEM_REGION, (i), \ + .setting.rdc_mem_region[0] = (msa), \ + .setting.rdc_mem_region[1] = (mea), \ + .setting.rdc_mem_region[2] = (mrc), \ + } + +void imx_rdc_init(const struct imx_rdc_cfg *cfg); + +#endif /* IMX_RDC_H */ + diff --git a/plat/intel/soc/agilex/aarch64/plat_helpers.S b/plat/intel/soc/agilex/aarch64/plat_helpers.S new file mode 100644 index 00000000..b3f5a5ea --- /dev/null +++ b/plat/intel/soc/agilex/aarch64/plat_helpers.S @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <cpu_macros.S> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl platform_is_primary_cpu + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + + .globl plat_get_my_entrypoint + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Wait until the it gets reset signal from rstmgr gets populated */ +poll_mailbox: + wfi + + mov_imm x0, PLAT_AGX_SEC_ENTRY + ldr x1, [x0] + mov_imm x2, PLAT_CPUID_RELEASE + ldr x3, [x2] + mrs x4, mpidr_el1 + and x4, x4, #0xff + cmp x3, x4 + b.ne poll_mailbox + br x1 +endfunc plat_secondary_cold_boot_setup + +func platform_is_primary_cpu + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc platform_is_primary_cpu + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + b platform_is_primary_cpu +endfunc plat_is_my_cpu_primary + +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 + +func plat_get_my_entrypoint + mov_imm x1, PLAT_AGX_SEC_ENTRY + ldr x0, [x1] + ret +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * 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, PLAT_UART0_BASE + mov_imm x1, PLAT_UART_CLOCK + mov_imm x2, PLAT_BAUDRATE + b console_16550_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(void) + * 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, PLAT_UART0_BASE + b console_16550_core_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_16550_core_flush +endfunc plat_crash_console_flush + + + /* -------------------------------------------------------- + * void platform_mem_init (void); + * + * Any memory init, relocation to be done before the + * platform boots. Called very early in the boot process. + * -------------------------------------------------------- + */ +func platform_mem_init + mov x0, #0 + ret +endfunc platform_mem_init diff --git a/plat/intel/soc/agilex/aarch64/platform_common.c b/plat/intel/soc/agilex/aarch64/platform_common.c new file mode 100644 index 00000000..6d3d817d --- /dev/null +++ b/plat/intel/soc/agilex/aarch64/platform_common.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <platform_def.h> +#include <plat/common/platform.h> +#include <socfpga_private.h> + + +unsigned int plat_get_syscnt_freq2(void) +{ + return PLAT_SYS_COUNTER_FREQ_IN_TICKS; +} + +unsigned long socfpga_get_ns_image_entrypoint(void) +{ + return PLAT_NS_IMAGE_OFFSET; +} + +/****************************************************************************** + * Gets SPSR for BL32 entry + *****************************************************************************/ +uint32_t socfpga_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/****************************************************************************** + * Gets SPSR for BL33 entry + *****************************************************************************/ +uint32_t socfpga_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* 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; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + diff --git a/plat/intel/soc/agilex/bl2_plat_mem_params_desc.c b/plat/intel/soc/agilex/bl2_plat_mem_params_desc.c new file mode 100644 index 00000000..4f756656 --- /dev/null +++ b/plat/intel/soc/agilex/bl2_plat_mem_params_desc.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <platform_def.h> +#include <plat/common/platform.h> + + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + +#else /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, +#endif /* EL3_PAYLOAD_BASE */ + + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.pc = PLAT_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_NS_IMAGE_OFFSET, + .image_info.image_max_size = + 0x0 + 0x40000000 - PLAT_NS_IMAGE_OFFSET, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c new file mode 100644 index 00000000..385065f9 --- /dev/null +++ b/plat/intel/soc/agilex/bl2_plat_setup.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/generic_delay_timer.h> +#include <drivers/synopsys/dw_mmc.h> +#include <drivers/ti/uart/uart_16550.h> +#include <lib/xlat_tables/xlat_tables.h> +#include <platform_def.h> +#include <socfpga_private.h> + +#include "agilex_clock_manager.h" +#include "agilex_handoff.h" +#include "agilex_mailbox.h" +#include "agilex_memory_controller.h" +#include "agilex_pinmux.h" +#include "agilex_private.h" +#include "agilex_reset_manager.h" +#include "agilex_system_manager.h" + +#include "ccu/ncore_ccu.h" +#include "qspi/cadence_qspi.h" +#include "wdt/watchdog.h" + + +const mmap_region_t agilex_plat_mmap[] = { + MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, + MT_MEMORY | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, + MT_DEVICE | MT_RW | MT_NS), + {0}, +}; + +boot_source_type boot_source; + +void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1, + u_register_t x2, u_register_t x4) +{ + static console_16550_t console; + handoff reverse_handoff_ptr; + + generic_delay_timer_init(); + + if (agilex_get_handoff(&reverse_handoff_ptr)) + return; + config_pinmux(&reverse_handoff_ptr); + boot_source = reverse_handoff_ptr.boot_source; + config_clkmgr_handoff(&reverse_handoff_ptr); + + enable_nonsecure_access(); + deassert_peripheral_reset(); + config_hps_hs_before_warm_reset(); + + watchdog_init(get_wdt_clk(&reverse_handoff_ptr)); + + console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE, + &console); + + socfpga_delay_timer_init(); + init_ncore_ccu(); + init_hard_memory_controller(); + enable_ns_bridge_access(); +} + + +void bl2_el3_plat_arch_setup(void) +{ + + struct mmc_device_info info; + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL2_BASE, BL2_END - BL2_BASE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE), + MAP_REGION_FLAT(BL_RO_DATA_BASE, + BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE), +#if USE_COHERENT_MEM_BAR + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0}, + }; + + setup_page_tables(bl_regions, agilex_plat_mmap); + + enable_mmu_el3(0); + + dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000); + + info.mmc_dev_type = MMC_IS_SD; + info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3; + + mailbox_init(); + + switch (boot_source) { + case BOOT_SOURCE_SDMMC: + dw_mmc_init(¶ms, &info); + socfpga_io_setup(boot_source); + break; + + case BOOT_SOURCE_QSPI: + mailbox_set_qspi_open(); + mailbox_set_qspi_direct(); + cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL, + QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS, + QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0); + socfpga_io_setup(boot_source); + break; + + default: + ERROR("Unsupported boot source\n"); + panic(); + break; + } +} + +uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* 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; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + switch (image_id) { + case BL33_IMAGE_ID: + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = get_spsr_for_bl33_entry(); + break; + default: + break; + } + + return 0; +} + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl2_platform_setup(void) +{ +} + diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c new file mode 100644 index 00000000..03fba8aa --- /dev/null +++ b/plat/intel/soc/agilex/bl31_plat_setup.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <assert.h> +#include <common/bl_common.h> +#include <drivers/arm/gicv2.h> +#include <drivers/ti/uart/uart_16550.h> +#include <lib/xlat_tables/xlat_tables.h> +#include <platform_def.h> + + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_16550_t console; + + console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE, + &console); + /* + * Check params passed from BL31 should not be NULL, + */ + void *from_bl2 = (void *) arg0; + + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + /* + * Copy BL32 (if populated by BL31) and BL33 entry point information. + * They are stored in Secure RAM, in BL31's address space. + */ + + bl_params_node_t *bl_params = params_from_bl2->head; + + while (bl_params) { + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +static const interrupt_prop_t s10_interrupt_props[] = { + PLAT_INTEL_AGX_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_INTEL_AGX_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t plat_gicv2_gic_data = { + .gicd_base = PLAT_INTEL_AGX_GICD_BASE, + .gicc_base = PLAT_INTEL_AGX_GICC_BASE, + .interrupt_props = s10_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(s10_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + /* Initialize the gic cpu and distributor interfaces */ + gicv2_driver_init(&plat_gicv2_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +const mmap_region_t plat_agilex_mmap[] = { + MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, MT_DEVICE | MT_RW | MT_NS), + {0}, +}; + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE), + MAP_REGION_FLAT(BL_RO_DATA_BASE, + BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE), +#if USE_COHERENT_MEM + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0}, + }; + + setup_page_tables(bl_regions, plat_agilex_mmap); + enable_mmu_el3(0); +} + diff --git a/plat/intel/soc/agilex/include/agilex_clock_manager.h b/plat/intel/soc/agilex/include/agilex_clock_manager.h new file mode 100644 index 00000000..c1a7546c --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_clock_manager.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CLOCKMANAGER_H +#define CLOCKMANAGER_H + +#include "agilex_handoff.h" + +/* Clock Manager Registers */ +#define CLKMGR_OFFSET 0xffd10000 + +#define CLKMGR_CTRL 0x0 +#define CLKMGR_STAT 0x4 +#define CLKMGR_INTRCLR 0x14 + +/* Main PLL Group */ +#define CLKMGR_MAINPLL 0xffd10024 +#define CLKMGR_MAINPLL_EN 0x0 +#define CLKMGR_MAINPLL_BYPASS 0xc +#define CLKMGR_MAINPLL_MPUCLK 0x18 +#define CLKMGR_MAINPLL_NOCCLK 0x1c +#define CLKMGR_MAINPLL_NOCDIV 0x20 +#define CLKMGR_MAINPLL_PLLGLOB 0x24 +#define CLKMGR_MAINPLL_FDBCK 0x28 +#define CLKMGR_MAINPLL_MEM 0x2c +#define CLKMGR_MAINPLL_MEMSTAT 0x30 +#define CLKMGR_MAINPLL_PLLC0 0x34 +#define CLKMGR_MAINPLL_PLLC1 0x38 +#define CLKMGR_MAINPLL_VCOCALIB 0x3c +#define CLKMGR_MAINPLL_PLLC2 0x40 +#define CLKMGR_MAINPLL_PLLC3 0x44 +#define CLKMGR_MAINPLL_PLLM 0x48 + +/* Peripheral PLL Group */ +#define CLKMGR_PERPLL 0xffd1007c +#define CLKMGR_PERPLL_EN 0x0 +#define CLKMGR_PERPLL_BYPASS 0xc +#define CLKMGR_PERPLL_EMACCTL 0x18 +#define CLKMGR_PERPLL_GPIODIV 0x1c +#define CLKMGR_PERPLL_PLLGLOB 0x20 +#define CLKMGR_PERPLL_FDBCK 0x24 +#define CLKMGR_PERPLL_MEM 0x28 +#define CLKMGR_PERPLL_MEMSTAT 0x2c +#define CLKMGR_PERPLL_PLLC0 0x30 +#define CLKMGR_PERPLL_PLLC1 0x34 +#define CLKMGR_PERPLL_VCOCALIB 0x38 +#define CLKMGR_PERPLL_PLLC2 0x3c +#define CLKMGR_PERPLL_PLLC3 0x40 +#define CLKMGR_PERPLL_PLLM 0x44 + +/* Altera Group */ +#define CLKMGR_ALTERA 0xffd100d0 +#define CLKMGR_ALTERA_JTAG 0x0 +#define CLKMGR_ALTERA_EMACACTR 0x4 +#define CLKMGR_ALTERA_EMACBCTR 0x8 +#define CLKMGR_ALTERA_EMACPTPCTR 0xc +#define CLKMGR_ALTERA_GPIODBCTR 0x10 +#define CLKMGR_ALTERA_SDMMCCTR 0x14 +#define CLKMGR_ALTERA_S2FUSER0CTR 0x18 +#define CLKMGR_ALTERA_S2FUSER1CTR 0x1c +#define CLKMGR_ALTERA_PSIREFCTR 0x20 +#define CLKMGR_ALTERA_EXTCNTRST 0x24 + +/* Membus */ +#define CLKMGR_MEM_REQ BIT(24) +#define CLKMGR_MEM_WR BIT(25) +#define CLKMGR_MEM_ERR BIT(26) +#define CLKMGR_MEM_WDAT_OFFSET 16 +#define CLKMGR_MEM_ADDR 0x4027 +#define CLKMGR_MEM_WDAT 0x80 + +/* Clock Manager Macros */ +#define CLKMGR_CTRL_BOOTMODE_SET_MSK 0x00000001 +#define CLKMGR_STAT_BUSY_E_BUSY 0x1 +#define CLKMGR_STAT_BUSY(x) (((x) & 0x00000001) >> 0) +#define CLKMGR_STAT_MAINPLLLOCKED(x) (((x) & 0x00000100) >> 8) +#define CLKMGR_STAT_PERPLLLOCKED(x) (((x) & 0x00010000) >> 16) +#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK 0x00000004 +#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK 0x00000008 + +/* Main PLL Macros */ +#define CLKMGR_MAINPLL_EN_RESET 0x000000ff +#define CLKMGR_MAINPLL_PLLM_MDIV(x) ((x) & 0x000003ff) +#define CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK 0x00000001 +#define CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK 0x00000002 + +#define CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8) +#define CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV(x) (((x) & 0x00000f00) >> 8) +#define CLKMGR_MAINPLL_PLLGLOB_DREFCLKDIV(x) (((x) & 0x00003000) >> 12) + +#define CLKMGR_MAINPLL_PLLGLOB_PSRC(x) (((x) & 0x00030000) >> 16) +#define CLKMGR_MAINPLL_PLLGLOB_PSRC_EOSC1 0x0 +#define CLKMGR_MAINPLL_PLLGLOB_PSRC_INTOSC 0x1 +#define CLKMGR_MAINPLL_PLLGLOB_PSRC_F2S 0x2 +#define CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000003ff) +#define CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(x) (((x) << 16) & 0x00ff0000) + +/* Peripheral PLL Macros */ +#define CLKMGR_PERPLL_EN_RESET 0x00000fff +#define CLKMGR_PERPLL_PLLM_MDIV(x) ((x) & 0x000003ff) +#define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x) (((x) << 0) & 0x0000ffff) +#define CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK 0x00000001 + +#define CLKMGR_PERPLL_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8) +#define CLKMGR_PERPLL_PLLGLOB_AREFCLKDIV(x) (((x) & 0x00000f00) >> 8) +#define CLKMGR_PERPLL_PLLGLOB_DREFCLKDIV(x) (((x) & 0x00003000) >> 12) + +#define CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK 0x00000002 +#define CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000003ff) +#define CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(x) (((x) << 16) & 0x00ff0000) + +/* Altera Macros */ +#define CLKMGR_ALTERA_EXTCNTRST_RESET 0xff + + +typedef struct { + uint32_t clk_freq_of_eosc1; + uint32_t clk_freq_of_f2h_free; + uint32_t clk_freq_of_cb_intosc_ls; +} CLOCK_SOURCE_CONFIG; + +void config_clkmgr_handoff(handoff *hoff_ptr); +int get_wdt_clk(handoff *hoff_ptr); + +#endif diff --git a/plat/intel/soc/agilex/include/agilex_handoff.h b/plat/intel/soc/agilex/include/agilex_handoff.h new file mode 100644 index 00000000..20164061 --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_handoff.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HANDOFF_H +#define HANDOFF_H + +#define HANDOFF_MAGIC_HEADER 0x424f4f54 /* BOOT */ +#define HANDOFF_MAGIC_PINMUX_SEL 0x504d5558 /* PMUX */ +#define HANDOFF_MAGIC_IOCTLR 0x494f4354 /* IOCT */ +#define HANDOFF_MAGIC_FPGA 0x46504741 /* FPGA */ +#define HANDOFF_MAGIC_IODELAY 0x444c4159 /* DLAY */ +#define HANDOFF_MAGIC_CLOCK 0x434c4b53 /* CLKS */ +#define HANDOFF_MAGIC_MISC 0x4d495343 /* MISC */ + +typedef struct handoff_t { + /* header */ + uint32_t header_magic; + uint32_t header_device; + uint32_t _pad_0x08_0x10[2]; + + /* pinmux configuration - select */ + uint32_t pinmux_sel_magic; + uint32_t pinmux_sel_length; + uint32_t _pad_0x18_0x20[2]; + uint32_t pinmux_sel_array[96]; /* offset, value */ + + /* pinmux configuration - io control */ + uint32_t pinmux_io_magic; + uint32_t pinmux_io_length; + uint32_t _pad_0x1a8_0x1b0[2]; + uint32_t pinmux_io_array[96]; /* offset, value */ + + /* pinmux configuration - use fpga switch */ + uint32_t pinmux_fpga_magic; + uint32_t pinmux_fpga_length; + uint32_t _pad_0x338_0x340[2]; + uint32_t pinmux_fpga_array[42]; /* offset, value */ + uint32_t _pad_0x3e8_0x3f0[2]; + + /* pinmux configuration - io delay */ + uint32_t pinmux_delay_magic; + uint32_t pinmux_delay_length; + uint32_t _pad_0x3f8_0x400[2]; + uint32_t pinmux_iodelay_array[96]; /* offset, value */ + + /* clock configuration */ + uint32_t clock_magic; + uint32_t clock_length; + uint32_t _pad_0x588_0x590[2]; + uint32_t main_pll_mpuclk; + uint32_t main_pll_nocclk; + uint32_t main_pll_nocdiv; + uint32_t main_pll_pllglob; + uint32_t main_pll_fdbck; + uint32_t main_pll_pllc0; + uint32_t main_pll_pllc1; + uint32_t main_pll_pllc2; + uint32_t main_pll_pllc3; + uint32_t main_pll_pllm; + uint32_t per_pll_emacctl; + uint32_t per_pll_gpiodiv; + uint32_t per_pll_pllglob; + uint32_t per_pll_fdbck; + uint32_t per_pll_pllc0; + uint32_t per_pll_pllc1; + uint32_t per_pll_pllc2; + uint32_t per_pll_pllc3; + uint32_t per_pll_pllm; + uint32_t alt_emacactr; + uint32_t alt_emacbctr; + uint32_t alt_emacptpctr; + uint32_t alt_gpiodbctr; + uint32_t alt_sdmmcctr; + uint32_t alt_s2fuser0ctr; + uint32_t alt_s2fuser1ctr; + uint32_t alt_psirefctr; + uint32_t hps_osc_clk_h; + uint32_t fpga_clk_hz; + uint32_t _pad_0x604_0x610[3]; + + /* misc configuration */ + uint32_t misc_magic; + uint32_t misc_length; + uint32_t _pad_0x618_0x620[2]; + uint32_t boot_source; +} handoff; + +int verify_handoff_image(handoff *hoff_ptr, handoff *reverse_hoff_ptr); +int agilex_get_handoff(handoff *hoff_ptr); + +#endif + + diff --git a/plat/intel/soc/agilex/include/agilex_mailbox.h b/plat/intel/soc/agilex/include/agilex_mailbox.h new file mode 100644 index 00000000..cd8be289 --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_mailbox.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_MBOX_H +#define AGX_MBOX_H + +#include <lib/utils_def.h> + +#define MBOX_OFFSET 0xffa30000 + +#define MBOX_ATF_CLIENT_ID 0x1 +#define MBOX_JOB_ID 0x1 + +/* Mailbox interrupt flags and masks */ +#define MBOX_INT_FLAG_COE 0x1 +#define MBOX_INT_FLAG_RIE 0x2 +#define MBOX_INT_FLAG_UAE 0x100 +#define MBOX_COE_BIT(INTERRUPT) ((INTERRUPT) & 0x3) +#define MBOX_UAE_BIT(INTERRUPT) (((INTERRUPT) & (1<<8))) + +/* Mailbox response and status */ +#define MBOX_RESP_BUFFER_SIZE 16 +#define MBOX_RESP_ERR(BUFFER) ((BUFFER) & 0x00000fff) +#define MBOX_RESP_LEN(BUFFER) (((BUFFER) & 0x007ff000) >> 12) +#define MBOX_RESP_CLIENT_ID(BUFFER) (((BUFFER) & 0xf0000000) >> 28) +#define MBOX_RESP_JOB_ID(BUFFER) (((BUFFER) & 0x0f000000) >> 24) +#define MBOX_STATUS_UA_MASK (1<<8) + +/* Mailbox command and response */ +#define MBOX_CMD_FREE_OFFSET 0x14 +#define MBOX_CMD_BUFFER_SIZE 32 +#define MBOX_CLIENT_ID_CMD(CLIENT_ID) ((CLIENT_ID) << 28) +#define MBOX_JOB_ID_CMD(JOB_ID) (JOB_ID<<24) +#define MBOX_CMD_LEN_CMD(CMD_LEN) ((CMD_LEN) << 12) +#define MBOX_INDIRECT (1 << 11) +#define MBOX_INSUFFICIENT_BUFFER -2 +#define MBOX_CIN 0x00 +#define MBOX_ROUT 0x04 +#define MBOX_URG 0x08 +#define MBOX_INT 0x0C +#define MBOX_COUT 0x20 +#define MBOX_RIN 0x24 +#define MBOX_STATUS 0x2C +#define MBOX_CMD_BUFFER 0x40 +#define MBOX_RESP_BUFFER 0xC0 + +#define MBOX_RESP_BUFFER_SIZE 16 +#define MBOX_RESP_OK 0 +#define MBOX_RESP_INVALID_CMD 1 +#define MBOX_RESP_UNKNOWN_BR 2 +#define MBOX_RESP_UNKNOWN 3 +#define MBOX_RESP_NOT_CONFIGURED 256 + +/* Mailbox SDM doorbell */ +#define MBOX_DOORBELL_TO_SDM 0x400 +#define MBOX_DOORBELL_FROM_SDM 0x480 + +/* Mailbox QSPI commands */ +#define MBOX_CMD_RESTART 2 +#define MBOX_CMD_QSPI_OPEN 50 +#define MBOX_CMD_QSPI_CLOSE 51 +#define MBOX_CMD_QSPI_DIRECT 59 +#define MBOX_CMD_GET_IDCODE 16 +#define MBOX_CMD_QSPI_SET_CS 52 + +/* Mailbox REBOOT commands */ +#define MBOX_CMD_REBOOT_HPS 71 + +/* Generic error handling */ +#define MBOX_TIMEOUT -2047 +#define MBOX_NO_RESPONSE -2 +#define MBOX_WRONG_ID -3 + +/* Mailbox status */ +#define RECONFIG_STATUS_STATE 0 +#define RECONFIG_STATUS_PIN_STATUS 2 +#define RECONFIG_STATUS_SOFTFUNC_STATUS 3 +#define PIN_STATUS_NSTATUS (U(1) << 31) +#define SOFTFUNC_STATUS_SEU_ERROR (1 << 3) +#define SOFTFUNC_STATUS_INIT_DONE (1 << 1) +#define SOFTFUNC_STATUS_CONF_DONE (1 << 0) +#define MBOX_CFGSTAT_STATE_CONFIG 0x10000000 + +/* SMC function IDs for SiP Service queries */ +#define SIP_SVC_CALL_COUNT 0x8200ff00 +#define SIP_SVC_UID 0x8200ff01 +#define SIP_SVC_VERSION 0x8200ff03 + +/* SiP Service Calls version numbers */ +#define SIP_SVC_VERSION_MAJOR 0 +#define SIP_SVC_VERSION_MINOR 1 + +/* Mailbox reconfiguration commands */ +#define MBOX_RECONFIG 6 +#define MBOX_RECONFIG_DATA 8 +#define MBOX_RECONFIG_STATUS 9 + +/* Sip get memory */ +#define INTEL_SIP_SMC_FPGA_CONFIG_START 0xC2000001 +#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM 0xC2000005 +#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE 0xC2000004 +#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE 0x42000002 +#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE 0xC2000003 +#define INTEL_SIP_SMC_STATUS_OK 0 +#define INTEL_SIP_SMC_STATUS_ERROR 0x4 +#define INTEL_SIP_SMC_STATUS_BUSY 0x1 +#define INTEL_SIP_SMC_STATUS_REJECTED 0x2 +#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x1000 +#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 16777216 + +void mailbox_set_int(int interrupt_input); +int mailbox_init(void); +void mailbox_set_qspi_close(void); +void mailbox_set_qspi_open(void); +void mailbox_set_qspi_direct(void); +int mailbox_send_cmd(int job_id, unsigned int cmd, uint32_t *args, + int len, int urgent, uint32_t *response); +void mailbox_send_cmd_async(int job_id, unsigned int cmd, uint32_t *args, + int len, int urgent); +int mailbox_read_response(int job_id, uint32_t *response); +int mailbox_get_qspi_clock(void); +void mailbox_reset_cold(void); + +#endif diff --git a/plat/intel/soc/agilex/include/agilex_memory_controller.h b/plat/intel/soc/agilex/include/agilex_memory_controller.h new file mode 100644 index 00000000..c0c94e65 --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_memory_controller.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_MEMORYCONTROLLER_H +#define AGX_MEMORYCONTROLLER_H + +#define AGX_MPFE_IOHMC_REG_DRAMADDRW 0xf80100a8 +#define AGX_MPFE_IOHMC_CTRLCFG0 0xf8010028 +#define AGX_MPFE_IOHMC_CTRLCFG1 0xf801002c +#define AGX_MPFE_IOHMC_DRAMADDRW 0xf80100a8 +#define AGX_MPFE_IOHMC_DRAMTIMING0 0xf8010050 +#define AGX_MPFE_IOHMC_CALTIMING0 0xf801007c +#define AGX_MPFE_IOHMC_CALTIMING1 0xf8010080 +#define AGX_MPFE_IOHMC_CALTIMING2 0xf8010084 +#define AGX_MPFE_IOHMC_CALTIMING3 0xf8010088 +#define AGX_MPFE_IOHMC_CALTIMING4 0xf801008c +#define AGX_MPFE_IOHMC_CALTIMING9 0xf80100a0 +#define AGX_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(x) (((x) & 0x000000ff) >> 0) +#define AGX_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(value) \ + (((value) & 0x00000060) >> 5) + +#define AGX_RSTMGR_BRGMODRST 0xffd1102c +#define AGX_RSTMGR_BRGMODRST_DDRSCH 0x00000040 + +#define AGX_MPFE_HMC_ADP_ECCCTRL1 0xf8011100 +#define AGX_MPFE_HMC_ADP_ECCCTRL2 0xf8011104 +#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT 0xf8011218 +#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE 0x000000ff +#define AGX_MPFE_HMC_ADP_RSTHANDSHAKECTRL 0xf8011214 + + +#define AGX_MPFE_IOHMC_REG_CTRLCFG1 0xf801002c + +#define AGX_MPFE_IOHMC_REG_NIOSRESERVE0_OFST 0xf8010110 + +#define IOHMC_DRAMADDRW_COL_ADDR_WIDTH(x) (((x) & 0x0000001f) >> 0) +#define IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(x) (((x) & 0x000003e0) >> 5) +#define IOHMC_DRAMADDRW_CS_ADDR_WIDTH(x) (((x) & 0x00070000) >> 16) +#define IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(x) (((x) & 0x0000c000) >> 14) +#define IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(x) (((x) & 0x00003c00) >> 10) + +#define AGX_MPFE_DDR(x) (0xf8000000 + x) +#define AGX_MPFE_HMC_ADP_DDRCALSTAT 0xf801100c +#define AGX_MPFE_DDR_MAIN_SCHED 0xf8000400 +#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF 0xf8000408 +#define AGX_MPFE_DDR_MAIN_SCHED_DDRTIMING 0xf800040c +#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK 0x0000001f +#define AGX_MPFE_DDR_MAIN_SCHED_DDRMODE 0xf8000410 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV 0xf800043c +#define AGX_MPFE_DDR_MAIN_SCHED_READLATENCY 0xf8000414 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE 0xf8000438 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST 10 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST 4 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST 0 +#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(x) (((x) << 0) & 0x0000001f) +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST 0 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK (BIT(0) | BIT(1)) +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST 2 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK (BIT(2) | BIT(3)) +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST 4 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK (BIT(4) | BIT(5)) + +#define AGX_MPFE_HMC_ADP(x) (0xf8011000 + (x)) +#define AGX_MPFE_HMC_ADP_HPSINTFCSEL 0xf8011210 +#define AGX_MPFE_HMC_ADP_DDRIOCTRL 0xf8011008 +#define HMC_ADP_DDRIOCTRL 0x8 +#define HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0) +#define HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(x) (((x) & 0x00003e00) >> 9) +#define ADP_DRAMADDRWIDTH 0xe0 + +#define ACT_TO_ACT_DIFF_BANK(value) (((value) & 0x00fc0000) >> 18) +#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12) +#define ACT_TO_RDWR(value) (((value) & 0x0000003f) >> 0) +#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12) + +/* timing 2 */ +#define RD_TO_RD_DIFF_CHIP(value) (((value) & 0x00000fc0) >> 6) +#define RD_TO_WR_DIFF_CHIP(value) (((value) & 0x3f000000) >> 24) +#define RD_TO_WR(value) (((value) & 0x00fc0000) >> 18) +#define RD_TO_PCH(value) (((value) & 0x00000fc0) >> 6) + +/* timing 3 */ +#define CALTIMING3_WR_TO_RD_DIFF_CHIP(value) (((value) & 0x0003f000) >> 12) +#define CALTIMING3_WR_TO_RD(value) (((value) & 0x00000fc0) >> 6) + +/* timing 4 */ +#define PCH_TO_VALID(value) (((value) & 0x00000fc0) >> 6) + +#define DDRTIMING_BWRATIO_OFST 31 +#define DDRTIMING_WRTORD_OFST 26 +#define DDRTIMING_RDTOWR_OFST 21 +#define DDRTIMING_BURSTLEN_OFST 18 +#define DDRTIMING_WRTOMISS_OFST 12 +#define DDRTIMING_RDTOMISS_OFST 6 +#define DDRTIMING_ACTTOACT_OFST 0 + +#define ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x3) >> 0) + +#define DDRMODE_AUTOPRECHARGE_OFST 1 +#define DDRMODE_BWRATIOEXTENDED_OFST 0 + + +#define AGX_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(x) (((x) & 0x7f) >> 0) +#define AGX_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(x) (((x) & 0x0f) >> 0) + +#define AGX_CCU_CPU0_MPRT_DDR 0xf7004400 +#define AGX_CCU_CPU0_MPRT_MEM0 0xf70045c0 +#define AGX_CCU_CPU0_MPRT_MEM1A 0xf70045e0 +#define AGX_CCU_CPU0_MPRT_MEM1B 0xf7004600 +#define AGX_CCU_CPU0_MPRT_MEM1C 0xf7004620 +#define AGX_CCU_CPU0_MPRT_MEM1D 0xf7004640 +#define AGX_CCU_CPU0_MPRT_MEM1E 0xf7004660 +#define AGX_CCU_IOM_MPRT_MEM0 0xf7018560 +#define AGX_CCU_IOM_MPRT_MEM1A 0xf7018580 +#define AGX_CCU_IOM_MPRT_MEM1B 0xf70185a0 +#define AGX_CCU_IOM_MPRT_MEM1C 0xf70185c0 +#define AGX_CCU_IOM_MPRT_MEM1D 0xf70185e0 +#define AGX_CCU_IOM_MPRT_MEM1E 0xf7018600 + +#define AGX_NOC_FW_DDR_SCR 0xf8020200 +#define AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT 0xf802021c +#define AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT 0xf8020218 +#define AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT 0xf802029c +#define AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT 0xf8020298 + +#define AGX_SOC_NOC_FW_DDR_SCR_ENABLE 0xf8020200 +#define AGX_CCU_NOC_DI_SET_MSK 0x10 + +#define AGX_SYSMGR_CORE_HMC_CLK 0xffd120b4 +#define AGX_SYSMGR_CORE_HMC_CLK_STATUS 0x00000001 + +#define AGX_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0(x) (((x) & 0xffff) >> 0) +#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK 0x00000003 +#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST 0 +#define AGX_MPFE_HMC_ADP_HPSINTFCSEL_ENABLE 0x001f1f1f +#define AGX_IOHMC_CTRLCFG1_ENABLE_ECC_OFST 7 + +#define AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK 0x00010000 +#define AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK 0x00000100 +#define AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK 0x00000001 + +#define AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK 0x00000001 +#define AGX_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK 0x00010000 +#define AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK 0x00000100 +#define AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(value) (((value) & 0x1) >> 0) + + +#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00003) >> 0) +#define IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(x) (((x) & 0x03c00) >> 10) +#define IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(x) (((x) & 0x0c000) >> 14) +#define IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(x) (((x) & 0x0001f) >> 0) +#define IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(x) (((x) & 0x70000) >> 16) +#define IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(x) (((x) & 0x003e0) >> 5) + +#define AGX_SDRAM_0_LB_ADDR 0x0 + +int init_hard_memory_controller(void); + +#endif diff --git a/plat/intel/soc/agilex/include/agilex_noc.h b/plat/intel/soc/agilex/include/agilex_noc.h new file mode 100644 index 00000000..22db3e28 --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_noc.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_NOC_H +#define AGX_NOC_H + + +#define AXI_AP (1<<0) +#define FPGA2SOC (1<<16) +#define MPU (1<<24) +#define AGX_NOC_PER_SCR_NAND 0xffd21000 +#define AGX_NOC_PER_SCR_NAND_DATA 0xffd21004 +#define AGX_NOC_PER_SCR_USB0 0xffd2100c +#define AGX_NOC_PER_SCR_USB1 0xffd21010 +#define AGX_NOC_PER_SCR_SPI_M0 0xffd2101c +#define AGX_NOC_PER_SCR_SPI_M1 0xffd21020 +#define AGX_NOC_PER_SCR_SPI_S0 0xffd21024 +#define AGX_NOC_PER_SCR_SPI_S1 0xffd21028 +#define AGX_NOC_PER_SCR_EMAC0 0xffd2102c +#define AGX_NOC_PER_SCR_EMAC1 0xffd21030 +#define AGX_NOC_PER_SCR_EMAC2 0xffd21034 +#define AGX_NOC_PER_SCR_SDMMC 0xffd21040 +#define AGX_NOC_PER_SCR_GPIO0 0xffd21044 +#define AGX_NOC_PER_SCR_GPIO1 0xffd21048 +#define AGX_NOC_PER_SCR_I2C0 0xffd21050 +#define AGX_NOC_PER_SCR_I2C1 0xffd21058 +#define AGX_NOC_PER_SCR_I2C2 0xffd2105c +#define AGX_NOC_PER_SCR_I2C3 0xffd21060 +#define AGX_NOC_PER_SCR_SP_TIMER0 0xffd21064 +#define AGX_NOC_PER_SCR_SP_TIMER1 0xffd21068 +#define AGX_NOC_PER_SCR_UART0 0xffd2106c +#define AGX_NOC_PER_SCR_UART1 0xffd21070 + + +#define AGX_NOC_SYS_SCR_DMA_ECC 0xffd21108 +#define AGX_NOC_SYS_SCR_EMAC0RX_ECC 0xffd2110c +#define AGX_NOC_SYS_SCR_EMAC0TX_ECC 0xffd21110 +#define AGX_NOC_SYS_SCR_EMAC1RX_ECC 0xffd21114 +#define AGX_NOC_SYS_SCR_EMAC1TX_ECC 0xffd21118 +#define AGX_NOC_SYS_SCR_EMAC2RX_ECC 0xffd2111c +#define AGX_NOC_SYS_SCR_EMAC2TX_ECC 0xffd21120 +#define AGX_NOC_SYS_SCR_NAND_ECC 0xffd2112c +#define AGX_NOC_SYS_SCR_NAND_READ_ECC 0xffd21130 +#define AGX_NOC_SYS_SCR_NAND_WRITE_ECC 0xffd21134 +#define AGX_NOC_SYS_SCR_OCRAM_ECC 0xffd21138 +#define AGX_NOC_SYS_SCR_SDMMC_ECC 0xffd21140 +#define AGX_NOC_SYS_SCR_USB0_ECC 0xffd21144 +#define AGX_NOC_SYS_SCR_USB1_ECC 0xffd21148 +#define AGX_NOC_SYS_SCR_CLK_MGR 0xffd2114c +#define AGX_NOC_SYS_SCR_IO_MGR 0xffd21154 +#define AGX_NOC_SYS_SCR_RST_MGR 0xffd21158 +#define AGX_NOC_SYS_SCR_SYS_MGR 0xffd2115c +#define AGX_NOC_SYS_SCR_OSC0_TIMER 0xffd21160 +#define AGX_NOC_SYS_SCR_OSC1_TIMER 0xffd21164 +#define AGX_NOC_SYS_SCR_WATCHDOG0 0xffd21168 +#define AGX_NOC_SYS_SCR_WATCHDOG1 0xffd2116c +#define AGX_NOC_SYS_SCR_WATCHDOG2 0xffd21170 +#define AGX_NOC_SYS_SCR_WATCHDOG3 0xffd21174 +#define AGX_NOC_SYS_SCR_DAP 0xffd21178 +#define AGX_NOC_SYS_SCR_L4_NOC_PROBES 0xffd21190 +#define AGX_NOC_SYS_SCR_L4_NOC_QOS 0xffd21194 + +#define AGX_CCU_NOC_BRIDGE_CPU0_RAM 0xf7004688 +#define AGX_CCU_NOC_BRIDGE_IOM_RAM 0xf7004688 + +#endif diff --git a/plat/intel/soc/agilex/include/agilex_pinmux.h b/plat/intel/soc/agilex/include/agilex_pinmux.h new file mode 100644 index 00000000..e6a7b341 --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_pinmux.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_PINMUX_H +#define AGX_PINMUX_H + +#define AGX_PINMUX_PIN0SEL 0xffd13000 +#define AGX_PINMUX_IO0CTRL 0xffd13130 +#define AGX_PINMUX_PINMUX_EMAC0_USEFPGA 0xffd13300 +#define AGX_PINMUX_IO0_DELAY 0xffd13400 + +#include "agilex_handoff.h" + +void config_pinmux(handoff *handoff); + +#endif + diff --git a/plat/intel/soc/agilex/include/agilex_private.h b/plat/intel/soc/agilex/include/agilex_private.h new file mode 100644 index 00000000..5ccbc8c3 --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_private.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_PRIVATE_H +#define AGX_PRIVATE_H + +#define AGX_MMC_REG_BASE 0xff808000 + +#define EMMC_DESC_SIZE (1<<20) +#define EMMC_INIT_PARAMS(base) \ + { .bus_width = MMC_BUS_WIDTH_4, \ + .clk_rate = 50000000, \ + .desc_base = (base), \ + .desc_size = EMMC_DESC_SIZE, \ + .flags = 0, \ + .reg_base = AGX_MMC_REG_BASE, \ + \ + } + +typedef enum { + BOOT_SOURCE_FPGA = 0, + BOOT_SOURCE_SDMMC, + BOOT_SOURCE_NAND, + BOOT_SOURCE_RSVD, + BOOT_SOURCE_QSPI, +} boot_source_type; + +void enable_nonsecure_access(void); +void socfpga_io_setup(int boot_source); + +#endif diff --git a/plat/intel/soc/agilex/include/agilex_reset_manager.h b/plat/intel/soc/agilex/include/agilex_reset_manager.h new file mode 100644 index 00000000..a1b6297c --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_reset_manager.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_RESETMANAGER_H +#define AGX_RESETMANAGER_H + +#define AGX_RSTMGR_HDSKEN 0xffd11010 +#define AGX_RSTMGR_PER0MODRST 0xffd11024 +#define AGX_RSTMGR_PER1MODRST 0xffd11028 +#define AGX_RSTMGR_BRGMODRST 0xffd1102c + +#define AGX_RSTMGR_PER0MODRST_EMAC0 0x00000001 +#define AGX_RSTMGR_PER0MODRST_EMAC1 0x00000002 +#define AGX_RSTMGR_PER0MODRST_EMAC2 0x00000004 +#define AGX_RSTMGR_PER0MODRST_USB0 0x00000008 +#define AGX_RSTMGR_PER0MODRST_USB1 0x00000010 +#define AGX_RSTMGR_PER0MODRST_NAND 0x00000020 +#define AGX_RSTMGR_PER0MODRST_SDMMC 0x00000080 +#define AGX_RSTMGR_PER0MODRST_EMAC0OCP 0x00000100 +#define AGX_RSTMGR_PER0MODRST_EMAC1OCP 0x00000200 +#define AGX_RSTMGR_PER0MODRST_EMAC2OCP 0x00000400 +#define AGX_RSTMGR_PER0MODRST_USB0OCP 0x00000800 +#define AGX_RSTMGR_PER0MODRST_USB1OCP 0x00001000 +#define AGX_RSTMGR_PER0MODRST_NANDOCP 0x00002000 +#define AGX_RSTMGR_PER0MODRST_SDMMCOCP 0x00008000 +#define AGX_RSTMGR_PER0MODRST_DMA 0x00010000 +#define AGX_RSTMGR_PER0MODRST_SPIM0 0x00020000 +#define AGX_RSTMGR_PER0MODRST_SPIM1 0x00040000 +#define AGX_RSTMGR_PER0MODRST_SPIS0 0x00080000 +#define AGX_RSTMGR_PER0MODRST_SPIS1 0x00100000 +#define AGX_RSTMGR_PER0MODRST_DMAOCP 0x00200000 +#define AGX_RSTMGR_PER0MODRST_EMACPTP 0x00400000 +#define AGX_RSTMGR_PER0MODRST_DMAIF0 0x01000000 +#define AGX_RSTMGR_PER0MODRST_DMAIF1 0x02000000 +#define AGX_RSTMGR_PER0MODRST_DMAIF2 0x04000000 +#define AGX_RSTMGR_PER0MODRST_DMAIF3 0x08000000 +#define AGX_RSTMGR_PER0MODRST_DMAIF4 0x10000000 +#define AGX_RSTMGR_PER0MODRST_DMAIF5 0x20000000 +#define AGX_RSTMGR_PER0MODRST_DMAIF6 0x40000000 +#define AGX_RSTMGR_PER0MODRST_DMAIF7 0x80000000 + +#define AGX_RSTMGR_PER1MODRST_WATCHDOG0 0x1 +#define AGX_RSTMGR_PER1MODRST_WATCHDOG1 0x2 +#define AGX_RSTMGR_PER1MODRST_WATCHDOG2 0x4 +#define AGX_RSTMGR_PER1MODRST_WATCHDOG3 0x8 +#define AGX_RSTMGR_PER1MODRST_L4SYSTIMER0 0x00000010 +#define AGX_RSTMGR_PER1MODRST_L4SYSTIMER1 0x00000020 +#define AGX_RSTMGR_PER1MODRST_SPTIMER0 0x00000040 +#define AGX_RSTMGR_PER1MODRST_SPTIMER1 0x00000080 +#define AGX_RSTMGR_PER1MODRST_I2C0 0x00000100 +#define AGX_RSTMGR_PER1MODRST_I2C1 0x00000200 +#define AGX_RSTMGR_PER1MODRST_I2C2 0x00000400 +#define AGX_RSTMGR_PER1MODRST_I2C3 0x00000800 +#define AGX_RSTMGR_PER1MODRST_I2C4 0x00001000 +#define AGX_RSTMGR_PER1MODRST_UART0 0x00010000 +#define AGX_RSTMGR_PER1MODRST_UART1 0x00020000 +#define AGX_RSTMGR_PER1MODRST_GPIO0 0x01000000 +#define AGX_RSTMGR_PER1MODRST_GPIO1 0x02000000 + +#define AGX_RSTMGR_HDSKEN_FPGAHSEN 0x00000004 +#define AGX_RSTMGR_HDSKEN_ETRSTALLEN 0x00000008 +#define AGX_RSTMGR_HDSKEN_L2FLUSHEN 0x00000100 +#define AGX_RSTMGR_HDSKEN_L3NOC_DBG 0x00010000 +#define AGX_RSTMGR_HDSKEN_DEBUG_L3NOC 0x00020000 +#define AGX_RSTMGR_HDSKEN_SDRSELFREFEN 0x00000001 + +#define AGX_RSTMGR_BRGMODRST_SOC2FPGA 0x1 +#define AGX_RSTMGR_BRGMODRST_LWHPS2FPGA 0x2 +#define AGX_RSTMGR_BRGMODRST_FPGA2SOC 0x4 +#define AGX_RSTMGR_BRGMODRST_MPFE 0x40 + +void deassert_peripheral_reset(void); +void config_hps_hs_before_warm_reset(void); + +#endif + diff --git a/plat/intel/soc/agilex/include/agilex_system_manager.h b/plat/intel/soc/agilex/include/agilex_system_manager.h new file mode 100644 index 00000000..6ec20842 --- /dev/null +++ b/plat/intel/soc/agilex/include/agilex_system_manager.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_SYSTEMMANAGER_H +#define AGX_SYSTEMMANAGER_H + +#define AGX_FIREWALL_SOC2FPGA 0xffd21200 +#define AGX_FIREWALL_LWSOC2FPGA 0xffd21300 + +#define AGX_NOC_FW_L4_PER_SCR_NAND_REGISTER 0xffd21000 +#define AGX_NOC_FW_L4_PER_SCR_NAND_DATA 0xffd21004 +#define AGX_NOC_FW_L4_PER_SCR_USB0_REGISTER 0xffd2100c +#define AGX_NOC_FW_L4_PER_SCR_USB1_REGISTER 0xffd21010 +#define AGX_NOC_FW_L4_PER_SCR_SPI_MASTER0 0xffd2101c +#define AGX_NOC_FW_L4_PER_SCR_SPI_MASTER1 0xffd21020 +#define AGX_NOC_FW_L4_PER_SCR_SPI_SLAVE0 0xffd21024 +#define AGX_NOC_FW_L4_PER_SCR_SPI_SLAVE1 0xffd21028 +#define AGX_NOC_FW_L4_PER_SCR_EMAC0 0xffd2102c +#define AGX_NOC_FW_L4_PER_SCR_EMAC1 0xffd21030 +#define AGX_NOC_FW_L4_PER_SCR_EMAC2 0xffd21034 +#define AGX_NOC_FW_L4_PER_SCR_SDMMC 0xffd21040 +#define AGX_NOC_FW_L4_PER_SCR_GPIO0 0xffd21044 +#define AGX_NOC_FW_L4_PER_SCR_GPIO1 0xffd21048 +#define AGX_NOC_FW_L4_PER_SCR_I2C0 0xffd21050 +#define AGX_NOC_FW_L4_PER_SCR_I2C1 0xffd21054 +#define AGX_NOC_FW_L4_PER_SCR_I2C2 0xffd21058 +#define AGX_NOC_FW_L4_PER_SCR_I2C3 0xffd2105c +#define AGX_NOC_FW_L4_PER_SCR_I2C4 0xffd21060 +#define AGX_NOC_FW_L4_PER_SCR_SP_TIMER0 0xffd21064 +#define AGX_NOC_FW_L4_PER_SCR_SP_TIMER1 0xffd21068 +#define AGX_NOC_FW_L4_PER_SCR_UART0 0xffd2106c +#define AGX_NOC_FW_L4_PER_SCR_UART1 0xffd21070 + +#define AGX_NOC_FW_L4_SYS_SCR_DMA_ECC 0xffd21108 +#define AGX_NOC_FW_L4_SYS_SCR_EMAC0RX_ECC 0xffd2110c +#define AGX_NOC_FW_L4_SYS_SCR_EMAC0TX_ECC 0xffd21110 +#define AGX_NOC_FW_L4_SYS_SCR_EMAC1RX_ECC 0xffd21114 +#define AGX_NOC_FW_L4_SYS_SCR_EMAC1TX_ECC 0xffd21118 +#define AGX_NOC_FW_L4_SYS_SCR_EMAC2RX_ECC 0xffd2111c +#define AGX_NOC_FW_L4_SYS_SCR_EMAC2TX_ECC 0xffd21120 +#define AGX_NOC_FW_L4_SYS_SCR_NAND_ECC 0xffd2112c +#define AGX_NOC_FW_L4_SYS_SCR_NAND_READ_ECC 0xffd21130 +#define AGX_NOC_FW_L4_SYS_SCR_NAND_WRITE_ECC 0xffd21134 +#define AGX_NOC_FW_L4_SYS_SCR_OCRAM_ECC 0xffd21138 +#define AGX_NOC_FW_L4_SYS_SCR_SDMMC_ECC 0xffd21140 +#define AGX_NOC_FW_L4_SYS_SCR_USB0_ECC 0xffd21144 +#define AGX_NOC_FW_L4_SYS_SCR_USB1_ECC 0xffd21148 +#define AGX_NOC_FW_L4_SYS_SCR_CLK_MGR 0xffd2114c +#define AGX_NOC_FW_L4_SYS_SCR_IO_MGR 0xffd21154 +#define AGX_NOC_FW_L4_SYS_SCR_RST_MGR 0xffd21158 +#define AGX_NOC_FW_L4_SYS_SCR_SYS_MGR 0xffd2115c +#define AGX_NOC_FW_L4_SYS_SCR_OSC0_TIMER 0xffd21160 +#define AGX_NOC_FW_L4_SYS_SCR_OSC1_TIMER 0xffd21164 +#define AGX_NOC_FW_L4_SYS_SCR_WATCHDOG0 0xffd21168 +#define AGX_NOC_FW_L4_SYS_SCR_WATCHDOG1 0xffd2116c +#define AGX_NOC_FW_L4_SYS_SCR_WATCHDOG2 0xffd21170 +#define AGX_NOC_FW_L4_SYS_SCR_WATCHDOG3 0xffd21174 +#define AGX_NOC_FW_L4_SYS_SCR_DAP 0xffd21178 +#define AGX_NOC_FW_L4_SYS_SCR_L4_NOC_PROBES 0xffd21190 +#define AGX_NOC_FW_L4_SYS_SCR_L4_NOC_QOS 0xffd21194 + +#define AGX_CCU_NOC_CPU0_RAMSPACE0_0 0xf7004688 +#define AGX_CCU_NOC_IOM_RAMSPACE0_0 0xf7018628 + +#define DISABLE_BRIDGE_FIREWALL 0x0ffe0101 +#define DISABLE_L4_FIREWALL (BIT(0) | BIT(16) | BIT(24)) + +void enable_nonsecure_access(void); +void enable_ns_bridge_access(void); + +#endif diff --git a/plat/intel/soc/agilex/include/plat_macros.S b/plat/intel/soc/agilex/include/plat_macros.S new file mode 100644 index 00000000..43db9a22 --- /dev/null +++ b/plat/intel/soc/agilex/include/plat_macros.S @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <platform_def.h> + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/intel/soc/agilex/include/platform_def.h b/plat/intel/soc/agilex/include/platform_def.h new file mode 100644 index 00000000..10f73386 --- /dev/null +++ b/plat/intel/soc/agilex/include/platform_def.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <common/interrupt_props.h> +#include <common/tbbr/tbbr_img_def.h> +#include <plat/common/common_def.h> + + +#define PLAT_CPUID_RELEASE 0xffe1b000 +#define PLAT_AGX_SEC_ENTRY 0xffe1b008 + +/* Define next boot image name and offset */ +#define PLAT_NS_IMAGE_OFFSET 0x50000 +#define PLAT_HANDOFF_OFFSET 0xFFE3F000 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/* Agilex supports up to 124GB RAM */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 39) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 39) + + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ +#define PLAT_PRIMARY_CPU 0 +#define PLAT_SECONDARY_ENTRY_BASE 0x01f78bf0 + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x2000 + +/* PSCI related constant */ +#define PLAT_NUM_POWER_DOMAINS 5 +#define PLAT_MAX_PWR_LVL 1 +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CLUSTER0_CORE_COUNT 4 +#define PLATFORM_CLUSTER1_CORE_COUNT 0 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER 4 + +/* Interrupt related constant */ + +#define INTEL_AGX_IRQ_SEC_PHY_TIMER 29 + +#define INTEL_AGX_IRQ_SEC_SGI_0 8 +#define INTEL_AGX_IRQ_SEC_SGI_1 9 +#define INTEL_AGX_IRQ_SEC_SGI_2 10 +#define INTEL_AGX_IRQ_SEC_SGI_3 11 +#define INTEL_AGX_IRQ_SEC_SGI_4 12 +#define INTEL_AGX_IRQ_SEC_SGI_5 13 +#define INTEL_AGX_IRQ_SEC_SGI_6 14 +#define INTEL_AGX_IRQ_SEC_SGI_7 15 + +#define TSP_IRQ_SEC_PHY_TIMER INTEL_AGX_IRQ_SEC_PHY_TIMER +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1) +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +#define DRAM_BASE (0x0) +#define DRAM_SIZE (0x80000000) + +#define OCRAM_BASE (0xFFE00000) +#define OCRAM_SIZE (0x00040000) + +#define MEM64_BASE (0x0100000000) +#define MEM64_SIZE (0x1F00000000) + +#define DEVICE1_BASE (0x80000000) +#define DEVICE1_SIZE (0x60000000) + +#define DEVICE2_BASE (0xF7000000) +#define DEVICE2_SIZE (0x08E00000) + +#define DEVICE3_BASE (0xFFFC0000) +#define DEVICE3_SIZE (0x00008000) + +#define DEVICE4_BASE (0x2000000000) +#define DEVICE4_SIZE (0x0100000000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL3-1 debug size plus a + * little space for growth. + */ + + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define BL1_RO_BASE (0xffe00000) +#define BL1_RO_LIMIT (0xffe0f000) +#define BL1_RW_BASE (0xffe10000) +#define BL1_RW_LIMIT (0xffe1ffff) +#define BL1_RW_SIZE (0x14000) + +#define BL2_BASE (0xffe00000) +#define BL2_LIMIT (0xffe1b000) + +#define BL31_BASE (0xffe1c000) +#define BL31_LIMIT (0xffe3bfff) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define MAX_XLAT_TABLES 8 +#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) + +#define PLAT_GIC_BASE (0xFFFC0000) +#define PLAT_GICC_BASE (PLAT_GIC_BASE + 0x2000) +#define PLAT_GICD_BASE (PLAT_GIC_BASE + 0x1000) +#define PLAT_GICR_BASE 0 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define PLAT_UART0_BASE (0xFFC02000) +#define PLAT_UART1_BASE (0xFFC02100) + +#define CRASH_CONSOLE_BASE PLAT_UART0_BASE + +#define PLAT_BAUDRATE (115200) +#define PLAT_UART_CLOCK (100000000) + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define PLAT_SYS_COUNTER_FREQ_IN_TICKS (400000000) +#define PLAT_SYS_COUNTER_FREQ_IN_MHZ (400) + +#define PLAT_INTEL_AGX_GICD_BASE PLAT_GICD_BASE +#define PLAT_INTEL_AGX_GICC_BASE PLAT_GICC_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_INTEL_AGX_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_AGX_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +#define PLAT_INTEL_AGX_G0_IRQ_PROPS(grp) + +#define MAX_IO_HANDLES 4 +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 2 + +#endif /* PLATFORM_DEF_H */ + diff --git a/plat/intel/soc/agilex/include/socfpga_private.h b/plat/intel/soc/agilex/include/socfpga_private.h new file mode 100644 index 00000000..6ab14090 --- /dev/null +++ b/plat/intel/soc/agilex/include/socfpga_private.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_PRIVATE_H +#define PLATFORM_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void socfgpa_configure_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 socfpga_configure_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 socfpga_delay_timer_init(void); + +void socfpga_gic_driver_init(void); + +uint32_t socfpga_get_spsr_for_bl32_entry(void); + +uint32_t socfpga_get_spsr_for_bl33_entry(void); + +unsigned long socfpga_get_ns_image_entrypoint(void); + + +#endif /* PLATFORM_PRIVATE_H */ diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk new file mode 100644 index 00000000..22ff1603 --- /dev/null +++ b/plat/intel/soc/agilex/platform.mk @@ -0,0 +1,73 @@ +# +# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2019, Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +PLAT_INCLUDES := \ + -Iplat/intel/soc/agilex/include/ \ + -Iplat/intel/soc/common/drivers/ + +PLAT_BL_COMMON_SOURCES := \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/common/plat_gicv2.c \ + plat/intel/soc/agilex/aarch64/platform_common.c \ + plat/intel/soc/agilex/aarch64/plat_helpers.S \ + +BL2_SOURCES += \ + common/desc_image_load.c \ + drivers/partition/partition.c \ + drivers/partition/gpt.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/mmc/mmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + drivers/io/io_storage.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/gpio/gpio.c \ + drivers/intel/soc/stratix10/io/s10_memmap_qspi.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/intel/soc/agilex/bl2_plat_setup.c \ + plat/intel/soc/agilex/socfpga_storage.c \ + plat/intel/soc/agilex/bl2_plat_mem_params_desc.c \ + plat/intel/soc/agilex/soc/agilex_reset_manager.c \ + plat/intel/soc/agilex/soc/agilex_handoff.c \ + plat/intel/soc/agilex/soc/agilex_clock_manager.c \ + plat/intel/soc/agilex/soc/agilex_pinmux.c \ + plat/intel/soc/agilex/soc/agilex_memory_controller.c \ + plat/intel/soc/agilex/socfpga_delay_timer.c \ + plat/intel/soc/agilex/socfpga_image_load.c \ + plat/intel/soc/agilex/soc/agilex_system_manager.c \ + plat/intel/soc/agilex/soc/agilex_mailbox.c \ + plat/intel/soc/common/drivers/qspi/cadence_qspi.c \ + plat/intel/soc/common/drivers/wdt/watchdog.c \ + plat/intel/soc/common/drivers/ccu/ncore_ccu.c + +BL31_SOURCES += \ + drivers/arm/cci/cci.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/aem_generic.S \ + plat/common/plat_psci_common.c \ + plat/intel/soc/agilex/socfpga_sip_svc.c \ + plat/intel/soc/agilex/bl31_plat_setup.c \ + plat/intel/soc/agilex/socfpga_psci.c \ + plat/intel/soc/agilex/socfpga_topology.c \ + plat/intel/soc/agilex/socfpga_delay_timer.c \ + plat/intel/soc/agilex/soc/agilex_reset_manager.c \ + plat/intel/soc/agilex/soc/agilex_pinmux.c \ + plat/intel/soc/agilex/soc/agilex_clock_manager.c \ + plat/intel/soc/agilex/soc/agilex_handoff.c \ + plat/intel/soc/agilex/soc/agilex_mailbox.c + +PROGRAMMABLE_RESET_ADDRESS := 0 +BL2_AT_EL3 := 1 +MULTI_CONSOLE_API := 1 +USE_COHERENT_MEM := 1 diff --git a/plat/intel/soc/agilex/soc/agilex_clock_manager.c b/plat/intel/soc/agilex/soc/agilex_clock_manager.c new file mode 100644 index 00000000..6e7b43e0 --- /dev/null +++ b/plat/intel/soc/agilex/soc/agilex_clock_manager.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <errno.h> +#include <lib/mmio.h> + +#include "agilex_clock_manager.h" +#include "agilex_handoff.h" + +static const CLOCK_SOURCE_CONFIG clk_source = { + /* clk_freq_of_eosc1 */ + (uint32_t) 25000000, + /* clk_freq_of_f2h_free */ + (uint32_t) 400000000, + /* clk_freq_of_cb_intosc_ls */ + (uint32_t) 50000000, +}; + +uint32_t wait_pll_lock(void) +{ + uint32_t data; + uint32_t count = 0; + + do { + data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT); + count++; + if (count >= 1000) + return -ETIMEDOUT; + + } while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) || + (CLKMGR_STAT_PERPLLLOCKED(data) == 0)); + return 0; +} + +uint32_t wait_fsm(void) +{ + uint32_t data; + uint32_t count = 0; + + do { + data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT); + count++; + if (count >= 1000) + return -ETIMEDOUT; + + } while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY); + + return 0; +} + +uint32_t pll_source_sync_config(uint32_t pll_mem_offset) +{ + uint32_t val = 0; + uint32_t count = 0; + uint32_t req_status = 0; + + val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ | + CLKMGR_MEM_WDAT << CLKMGR_MEM_WDAT_OFFSET | CLKMGR_MEM_ADDR); + mmio_write_32(pll_mem_offset, val); + + do { + req_status = mmio_read_32(pll_mem_offset); + count++; + } while ((req_status & CLKMGR_MEM_REQ) && (count < 10)); + + if (count >= 100) + return -ETIMEDOUT; + + return 0; +} + +uint32_t pll_source_sync_read(uint32_t pll_mem_offset) +{ + uint32_t val = 0; + uint32_t rdata = 0; + uint32_t count = 0; + uint32_t req_status = 0; + + val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR); + mmio_write_32(pll_mem_offset, val); + + do { + req_status = mmio_read_32(pll_mem_offset); + count++; + } while ((req_status & CLKMGR_MEM_REQ) && (count < 10)); + + if (count >= 100) + return -ETIMEDOUT; + + rdata = mmio_read_32(pll_mem_offset + 0x4); + INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata); + + return 0; +} + +void config_clkmgr_handoff(handoff *hoff_ptr) +{ + uint32_t mdiv, mscnt, hscnt; + uint32_t arefclk_div, drefclk_div; + + /* Bypass all mainpllgrp's clocks */ + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7); + wait_fsm(); + + /* Bypass all perpllgrp's clocks */ + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0x7f); + wait_fsm(); + + /* Put both PLL in reset and power down */ + mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK | + CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK); + mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK | + CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK); + + /* Setup main PLL dividers */ + mdiv = CLKMGR_MAINPLL_PLLM_MDIV(hoff_ptr->main_pll_pllm); + + arefclk_div = CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV( + hoff_ptr->main_pll_pllglob); + drefclk_div = CLKMGR_MAINPLL_PLLGLOB_DREFCLKDIV( + hoff_ptr->main_pll_pllglob); + + mscnt = 100 / (mdiv / BIT(drefclk_div)); + if (!mscnt) + mscnt = 1; + hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4; + + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB, + CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(hscnt) | + CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(mscnt)); + + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV, + hoff_ptr->main_pll_nocdiv); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, + hoff_ptr->main_pll_pllglob); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK, + hoff_ptr->main_pll_fdbck); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0, + hoff_ptr->main_pll_pllc0); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1, + hoff_ptr->main_pll_pllc1); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC2, + hoff_ptr->main_pll_pllc2); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC3, + hoff_ptr->main_pll_pllc3); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM, + hoff_ptr->main_pll_pllm); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MPUCLK, + hoff_ptr->main_pll_mpuclk); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK, + hoff_ptr->main_pll_nocclk); + + /* Setup peripheral PLL dividers */ + mdiv = CLKMGR_PERPLL_PLLM_MDIV(hoff_ptr->per_pll_pllm); + + arefclk_div = CLKMGR_PERPLL_PLLGLOB_AREFCLKDIV( + hoff_ptr->per_pll_pllglob); + drefclk_div = CLKMGR_PERPLL_PLLGLOB_DREFCLKDIV( + hoff_ptr->per_pll_pllglob); + + mscnt = 100 / (mdiv / BIT(drefclk_div)); + if (!mscnt) + mscnt = 1; + hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4; + + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB, + CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(hscnt) | + CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(mscnt)); + + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL, + hoff_ptr->per_pll_emacctl); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV, + CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET( + hoff_ptr->per_pll_gpiodiv)); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, + hoff_ptr->per_pll_pllglob); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK, + hoff_ptr->per_pll_fdbck); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0, + hoff_ptr->per_pll_pllc0); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1, + hoff_ptr->per_pll_pllc1); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC2, + hoff_ptr->per_pll_pllc2); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC3, + hoff_ptr->per_pll_pllc3); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM, + hoff_ptr->per_pll_pllm); + + /* Take both PLL out of reset and power up */ + mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK | + CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK); + mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK | + CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK); + + wait_pll_lock(); + + pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM); + pll_source_sync_read(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM); + + pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM); + pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM); + + /*Configure Ping Pong counters in altera group */ + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR, + hoff_ptr->alt_emacactr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACBCTR, + hoff_ptr->alt_emacbctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACPTPCTR, + hoff_ptr->alt_emacptpctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_GPIODBCTR, + hoff_ptr->alt_gpiodbctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR, + hoff_ptr->alt_sdmmcctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER0CTR, + hoff_ptr->alt_s2fuser0ctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER1CTR, + hoff_ptr->alt_s2fuser1ctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_PSIREFCTR, + hoff_ptr->alt_psirefctr); + + /* Take all PLLs out of bypass */ + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0); + wait_fsm(); + + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0); + wait_fsm(); + + /* Clear loss lock interrupt status register that */ + /* might be set during configuration */ + mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR, + CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK | + CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK); + + /* Take all ping pong counters out of reset */ + mmio_clrbits_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EXTCNTRST, + CLKMGR_ALTERA_EXTCNTRST_RESET); + + /* Set safe mode / out of boot mode */ + mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_CTRL, + CLKMGR_CTRL_BOOTMODE_SET_MSK); + wait_fsm(); + + /* Enable mainpllgrp's software-managed clock */ + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN, + CLKMGR_MAINPLL_EN_RESET); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN, + CLKMGR_PERPLL_EN_RESET); +} + +int get_wdt_clk(handoff *hoff_ptr) +{ + int main_noc_base_clk, l3_main_free_clk, l4_sys_free_clk; + int data32, mdiv, arefclkdiv, ref_clk; + + data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB); + + switch (CLKMGR_MAINPLL_PLLGLOB_PSRC(data32)) { + case CLKMGR_MAINPLL_PLLGLOB_PSRC_EOSC1: + ref_clk = clk_source.clk_freq_of_eosc1; + break; + case CLKMGR_MAINPLL_PLLGLOB_PSRC_INTOSC: + ref_clk = clk_source.clk_freq_of_cb_intosc_ls; + break; + case CLKMGR_MAINPLL_PLLGLOB_PSRC_F2S: + ref_clk = clk_source.clk_freq_of_f2h_free; + break; + default: + ref_clk = 0; + assert(0); + break; + } + + arefclkdiv = CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV(data32); + mdiv = CLKMGR_MAINPLL_PLLM_MDIV(hoff_ptr->main_pll_pllm); + + ref_clk = (ref_clk / arefclkdiv) * mdiv; + main_noc_base_clk = ref_clk / (hoff_ptr->main_pll_pllc1 & 0x7ff); + l3_main_free_clk = main_noc_base_clk / (hoff_ptr->main_pll_nocclk + 1); + l4_sys_free_clk = l3_main_free_clk / 4; + + return l4_sys_free_clk; +} diff --git a/plat/intel/soc/agilex/soc/agilex_handoff.c b/plat/intel/soc/agilex/soc/agilex_handoff.c new file mode 100644 index 00000000..a458686f --- /dev/null +++ b/plat/intel/soc/agilex/soc/agilex_handoff.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> +#include <string.h> + +#include "agilex_handoff.h" + +#define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | \ + (((x) & 0x0000FF00) << 8) | ((x) << 24)) + +int agilex_get_handoff(handoff *reverse_hoff_ptr) +{ + int i; + uint32_t *buffer; + handoff *handoff_ptr = (handoff *) PLAT_HANDOFF_OFFSET; + + memcpy(reverse_hoff_ptr, handoff_ptr, sizeof(handoff)); + buffer = (uint32_t *)reverse_hoff_ptr; + + /* convert big endian to little endian */ + for (i = 0; i < sizeof(handoff) / 4; i++) + buffer[i] = SWAP_UINT32(buffer[i]); + + if (reverse_hoff_ptr->header_magic != HANDOFF_MAGIC_HEADER) + return -1; + if (reverse_hoff_ptr->pinmux_sel_magic != HANDOFF_MAGIC_PINMUX_SEL) + return -1; + if (reverse_hoff_ptr->pinmux_io_magic != HANDOFF_MAGIC_IOCTLR) + return -1; + if (reverse_hoff_ptr->pinmux_fpga_magic != HANDOFF_MAGIC_FPGA) + return -1; + if (reverse_hoff_ptr->pinmux_delay_magic != HANDOFF_MAGIC_IODELAY) + return -1; + + return 0; +} diff --git a/plat/intel/soc/agilex/soc/agilex_mailbox.c b/plat/intel/soc/agilex/soc/agilex_mailbox.c new file mode 100644 index 00000000..ebfea614 --- /dev/null +++ b/plat/intel/soc/agilex/soc/agilex_mailbox.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/mmio.h> +#include <common/debug.h> + +#include "agilex_mailbox.h" + +static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args, + int len) +{ + uint32_t cmd_free_offset; + int i; + + cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN); + + if (cmd_free_offset >= MBOX_CMD_BUFFER_SIZE) { + INFO("Insufficient buffer in mailbox\n"); + return MBOX_INSUFFICIENT_BUFFER; + } + + + mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER + (cmd_free_offset++ * 4), + header_cmd); + + + for (i = 0; i < len; i++) { + cmd_free_offset %= MBOX_CMD_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER + + (cmd_free_offset++ * 4), args[i]); + } + + cmd_free_offset %= MBOX_CMD_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_CIN, cmd_free_offset); + + return 0; +} + +int mailbox_read_response(int job_id, uint32_t *response) +{ + int rin = 0; + int rout = 0; + int response_length = 0; + int resp = 0; + int total_resp_len = 0; + int timeout = 100000; + + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1); + + while (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) != 1) { + if (timeout-- < 0) + return MBOX_NO_RESPONSE; + } + + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0); + + rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); + + while (rout != rin) { + resp = mmio_read_32(MBOX_OFFSET + + MBOX_RESP_BUFFER + ((rout++)*4)); + + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + + if (MBOX_RESP_CLIENT_ID(resp) != MBOX_ATF_CLIENT_ID || + MBOX_RESP_JOB_ID(resp) != job_id) { + return MBOX_WRONG_ID; + } + + if (MBOX_RESP_ERR(resp) > 0) { + INFO("Error in response: %x\n", resp); + return -resp; + } + response_length = MBOX_RESP_LEN(resp); + + while (response_length) { + + response_length--; + resp = mmio_read_32(MBOX_OFFSET + + MBOX_RESP_BUFFER + + (rout)*4); + if (response) { + *(response + total_resp_len) = resp; + total_resp_len++; + } + rout++; + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + } + return total_resp_len; + } + + return MBOX_NO_RESPONSE; +} + + +int mailbox_poll_response(int job_id, int urgent, uint32_t *response) +{ + int timeout = 80000; + int rin = 0; + int rout = 0; + int response_length = 0; + int resp = 0; + int total_resp_len = 0; + + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1); + + while (1) { + while (timeout > 0 && + mmio_read_32(MBOX_OFFSET + + MBOX_DOORBELL_FROM_SDM) != 1) { + timeout--; + } + + if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) != 1) { + INFO("Timed out waiting for SDM"); + return MBOX_TIMEOUT; + } + + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0); + + if (urgent & 1) { + if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) & + MBOX_STATUS_UA_MASK) ^ + (urgent & MBOX_STATUS_UA_MASK)) { + mmio_write_32(MBOX_OFFSET + MBOX_URG, 0); + return 0; + } + + mmio_write_32(MBOX_OFFSET + MBOX_URG, 0); + INFO("Error: Mailbox did not get UA"); + return -1; + } + + rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); + + while (rout != rin) { + resp = mmio_read_32(MBOX_OFFSET + + MBOX_RESP_BUFFER + ((rout++)*4)); + + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + + if (MBOX_RESP_CLIENT_ID(resp) != MBOX_ATF_CLIENT_ID || + MBOX_RESP_JOB_ID(resp) != job_id) + continue; + + if (MBOX_RESP_ERR(resp) > 0) { + INFO("Error in response: %x\n", resp); + return -MBOX_RESP_ERR(resp); + } + response_length = MBOX_RESP_LEN(resp); + + while (response_length) { + + response_length--; + resp = mmio_read_32(MBOX_OFFSET + + MBOX_RESP_BUFFER + + (rout)*4); + if (response) { + *(response + total_resp_len) = resp; + total_resp_len++; + } + rout++; + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + } + return total_resp_len; + } + } +} + +void mailbox_send_cmd_async(int job_id, unsigned int cmd, uint32_t *args, + int len, int urgent) +{ + if (urgent) + mmio_write_32(MBOX_OFFSET + MBOX_URG, 1); + + fill_mailbox_circular_buffer(MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) | + MBOX_JOB_ID_CMD(job_id) | + MBOX_CMD_LEN_CMD(len) | + MBOX_INDIRECT | + cmd, args, len); +} + +int mailbox_send_cmd(int job_id, unsigned int cmd, uint32_t *args, + int len, int urgent, uint32_t *response) +{ + int status; + + if (urgent) { + urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) & + MBOX_STATUS_UA_MASK; + mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd); + status = 0; + } else { + status = fill_mailbox_circular_buffer( + MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) | + MBOX_JOB_ID_CMD(job_id) | + cmd, args, len); + } + + if (status) + return status; + + return mailbox_poll_response(job_id, urgent, response); +} + +void mailbox_set_int(int interrupt) +{ + + mmio_write_32(MBOX_OFFSET+MBOX_INT, MBOX_COE_BIT(interrupt) | + MBOX_UAE_BIT(interrupt)); +} + + +void mailbox_set_qspi_open(void) +{ + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, 0, 0, 0, 0); +} + +void mailbox_set_qspi_direct(void) +{ + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, 0, 0, 0, 0); +} + +void mailbox_set_qspi_close(void) +{ + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, 0, 0, 0, 0); +} + +int mailbox_get_qspi_clock(void) +{ + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + return mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, 0, 0, 0, 0); +} + +void mailbox_qspi_set_cs(int device_select) +{ + uint32_t cs_setting = device_select; + + /* QSPI device select settings at 31:28 */ + cs_setting = (cs_setting << 28); + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting, + 1, 0, 0); +} + +void mailbox_reset_cold(void) +{ + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0, 0, 0, 0); +} + +int mailbox_init(void) +{ + int status = 0; + + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE | + MBOX_INT_FLAG_UAE); + mmio_write_32(MBOX_OFFSET + MBOX_URG, 0); + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0); + status = mailbox_send_cmd(0, MBOX_CMD_RESTART, 0, 0, 1, 0); + + if (status) + return status; + + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + + return 0; +} + diff --git a/plat/intel/soc/agilex/soc/agilex_memory_controller.c b/plat/intel/soc/agilex/soc/agilex_memory_controller.c new file mode 100644 index 00000000..9fc3e0aa --- /dev/null +++ b/plat/intel/soc/agilex/soc/agilex_memory_controller.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> +#include <lib/mmio.h> +#include <lib/utils.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <platform_def.h> + +#include "agilex_memory_controller.h" + +#define ALT_CCU_NOC_DI_SET_MSK 0x10 + +#define DDR_READ_LATENCY_DELAY 40 +#define MAX_MEM_CAL_RETRY 3 +#define PRE_CALIBRATION_DELAY 1 +#define POST_CALIBRATION_DELAY 1 +#define TIMEOUT_EMIF_CALIBRATION 100 +#define CLEAR_EMIF_DELAY 50000 +#define CLEAR_EMIF_TIMEOUT 0x100000 +#define TIMEOUT_INT_RESP 10000 + +#define DDR_CONFIG(A, B, C, R) (((A) << 24) | ((B) << 16) | ((C) << 8) | (R)) +#define DDR_CONFIG_ELEMENTS (sizeof(ddr_config)/sizeof(uint32_t)) + +/* tWR = Min. 15ns constant, see JEDEC standard eg. DDR4 is JESD79-4.pdf */ +#define tWR_IN_NS 15 + +void configure_hmc_adaptor_regs(void); +void configure_ddr_sched_ctrl_regs(void); + +/* The followring are the supported configurations */ +uint32_t ddr_config[] = { + /* DDR_CONFIG(Address order,Bank,Column,Row) */ + /* List for DDR3 or LPDDR3 (pinout order > chip, row, bank, column) */ + DDR_CONFIG(0, 3, 10, 12), + DDR_CONFIG(0, 3, 9, 13), + DDR_CONFIG(0, 3, 10, 13), + DDR_CONFIG(0, 3, 9, 14), + DDR_CONFIG(0, 3, 10, 14), + DDR_CONFIG(0, 3, 10, 15), + DDR_CONFIG(0, 3, 11, 14), + DDR_CONFIG(0, 3, 11, 15), + DDR_CONFIG(0, 3, 10, 16), + DDR_CONFIG(0, 3, 11, 16), + DDR_CONFIG(0, 3, 12, 15), /* 0xa */ + /* List for DDR4 only (pinout order > chip, bank, row, column) */ + DDR_CONFIG(1, 3, 10, 14), + DDR_CONFIG(1, 4, 10, 14), + DDR_CONFIG(1, 3, 10, 15), + DDR_CONFIG(1, 4, 10, 15), + DDR_CONFIG(1, 3, 10, 16), + DDR_CONFIG(1, 4, 10, 16), + DDR_CONFIG(1, 3, 10, 17), + DDR_CONFIG(1, 4, 10, 17), +}; + +static int match_ddr_conf(uint32_t ddr_conf) +{ + int i; + + for (i = 0; i < DDR_CONFIG_ELEMENTS; i++) { + if (ddr_conf == ddr_config[i]) + return i; + } + return 0; +} + +static int check_hmc_clk(void) +{ + unsigned long timeout = 0; + uint32_t hmc_clk; + + do { + hmc_clk = mmio_read_32(AGX_SYSMGR_CORE_HMC_CLK); + if (hmc_clk & AGX_SYSMGR_CORE_HMC_CLK_STATUS) + break; + udelay(1); + } while (++timeout < 1000); + if (timeout >= 1000) + return -ETIMEDOUT; + + return 0; +} + +static int clear_emif(void) +{ + uint32_t data; + unsigned long timeout; + + mmio_write_32(AGX_MPFE_HMC_ADP_RSTHANDSHAKECTRL, 0); + + timeout = 0; + do { + data = mmio_read_32(AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT); + if ((data & AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE) == 0) + break; + udelay(CLEAR_EMIF_DELAY); + } while (++timeout < CLEAR_EMIF_TIMEOUT); + if (timeout >= CLEAR_EMIF_TIMEOUT) + return -ETIMEDOUT; + + return 0; +} + +static int mem_calibration(void) +{ + int status = 0; + uint32_t data; + unsigned long timeout; + unsigned long retry = 0; + + udelay(PRE_CALIBRATION_DELAY); + + do { + if (retry != 0) + INFO("DDR: Retrying DRAM calibration\n"); + + timeout = 0; + do { + data = mmio_read_32(AGX_MPFE_HMC_ADP_DDRCALSTAT); + if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 1) + break; + udelay(1); + } while (++timeout < TIMEOUT_EMIF_CALIBRATION); + + if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) { + status = clear_emif(); + if (status) + ERROR("Failed to clear Emif\n"); + } else { + break; + } + } while (++retry < MAX_MEM_CAL_RETRY); + + if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) { + ERROR("DDR: DRAM calibration failed.\n"); + status = -EIO; + } else { + INFO("DDR: DRAM calibration success.\n"); + status = 0; + } + + udelay(POST_CALIBRATION_DELAY); + + return status; +} + +int init_hard_memory_controller(void) +{ + int status; + + status = check_hmc_clk(); + if (status) { + ERROR("DDR: Error, HMC clock not running\n"); + return status; + } + +/* mmio_clrbits_32(AGX_RSTMGR_BRGMODRST, AGX_RSTMGR_BRGMODRST_DDRSCH);*/ + + status = mem_calibration(); + if (status) { + ERROR("DDR: Memory Calibration Failed\n"); + return status; + } + + configure_hmc_adaptor_regs(); +/* configure_ddr_sched_ctrl_regs();*/ + + return 0; +} + +void configure_ddr_sched_ctrl_regs(void) +{ + uint32_t data, dram_addr_order, ddr_conf, bank, row, col, + rd_to_miss, wr_to_miss, burst_len, burst_len_ddr_clk, + burst_len_sched_clk, act_to_act, rd_to_wr, wr_to_rd, bw_ratio, + t_rtp, t_rp, t_rcd, rd_latency, tw_rin_clk_cycles, + bw_ratio_extended, auto_precharge = 0, act_to_act_bank, faw, + faw_bank, bus_rd_to_rd, bus_rd_to_wr, bus_wr_to_rd; + + INFO("Init HPS NOC's DDR Scheduler.\n"); + + data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG1); + dram_addr_order = AGX_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_DRAMADDRW); + + col = IOHMC_DRAMADDRW_COL_ADDR_WIDTH(data); + row = IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(data); + bank = IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(data); + + ddr_conf = match_ddr_conf(DDR_CONFIG(dram_addr_order, bank, col, row)); + + if (ddr_conf) { + mmio_clrsetbits_32( + AGX_MPFE_DDR_MAIN_SCHED_DDRCONF, + AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK, + AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(ddr_conf)); + } else { + ERROR("DDR: Cannot find predefined ddrConf configuration.\n"); + } + + mmio_write_32(AGX_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data); + + data = mmio_read_32(AGX_MPFE_IOHMC_DRAMTIMING0); + rd_latency = AGX_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING0); + act_to_act = ACT_TO_ACT(data); + t_rcd = ACT_TO_RDWR(data); + act_to_act_bank = ACT_TO_ACT_DIFF_BANK(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING1); + rd_to_wr = RD_TO_WR(data); + bus_rd_to_rd = RD_TO_RD_DIFF_CHIP(data); + bus_rd_to_wr = RD_TO_WR_DIFF_CHIP(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING2); + t_rtp = RD_TO_PCH(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING3); + wr_to_rd = CALTIMING3_WR_TO_RD(data); + bus_wr_to_rd = CALTIMING3_WR_TO_RD_DIFF_CHIP(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING4); + t_rp = PCH_TO_VALID(data); + + data = mmio_read_32(AGX_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL)); + bw_ratio = ((HMC_ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 0 : 1); + + data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG0); + burst_len = HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(data); + burst_len_ddr_clk = burst_len / 2; + burst_len_sched_clk = ((burst_len/2) / 2); + + data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG0); + switch (AGX_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(data)) { + case 1: + /* DDR4 - 1333MHz */ + /* 20 (19.995) clock cycles = 15ns */ + /* Calculate with rounding */ + tw_rin_clk_cycles = (((tWR_IN_NS * 1333) % 1000) >= 500) ? + ((tWR_IN_NS * 1333) / 1000) + 1 : + ((tWR_IN_NS * 1333) / 1000); + break; + default: + /* Others - 1066MHz or slower */ + /* 16 (15.990) clock cycles = 15ns */ + /* Calculate with rounding */ + tw_rin_clk_cycles = (((tWR_IN_NS * 1066) % 1000) >= 500) ? + ((tWR_IN_NS * 1066) / 1000) + 1 : + ((tWR_IN_NS * 1066) / 1000); + break; + } + + rd_to_miss = t_rtp + t_rp + t_rcd - burst_len_sched_clk; + wr_to_miss = ((rd_latency + burst_len_ddr_clk + 2 + tw_rin_clk_cycles) + / 2) - rd_to_wr + t_rp + t_rcd; + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DDRTIMING, + bw_ratio << DDRTIMING_BWRATIO_OFST | + wr_to_rd << DDRTIMING_WRTORD_OFST| + rd_to_wr << DDRTIMING_RDTOWR_OFST | + burst_len_sched_clk << DDRTIMING_BURSTLEN_OFST | + wr_to_miss << DDRTIMING_WRTOMISS_OFST | + rd_to_miss << DDRTIMING_RDTOMISS_OFST | + act_to_act << DDRTIMING_ACTTOACT_OFST); + + data = mmio_read_32(AGX_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL)); + bw_ratio_extended = ((ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 1 : 0); + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DDRMODE, + bw_ratio_extended << DDRMODE_BWRATIOEXTENDED_OFST | + auto_precharge << DDRMODE_AUTOPRECHARGE_OFST); + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_READLATENCY, + (rd_latency / 2) + DDR_READ_LATENCY_DELAY); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING9); + faw = AGX_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(data); + + faw_bank = 1; // always 1 because we always have 4 bank DDR. + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE, + faw_bank << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST | + faw << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST | + act_to_act_bank << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST); + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV, + ((bus_rd_to_rd + << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST) + & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK) | + ((bus_rd_to_wr + << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST) + & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK) | + ((bus_wr_to_rd + << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST) + & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK)); + +} + +unsigned long get_physical_dram_size(void) +{ + uint32_t data; + unsigned long ram_addr_width, ram_ext_if_io_width; + + data = mmio_read_32(AGX_MPFE_HMC_ADP_DDRIOCTRL); + switch (AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(data)) { + case 0: + ram_ext_if_io_width = 16; + break; + case 1: + ram_ext_if_io_width = 32; + break; + case 2: + ram_ext_if_io_width = 64; + break; + default: + ram_ext_if_io_width = 0; + break; + } + + data = mmio_read_32(AGX_MPFE_IOHMC_REG_DRAMADDRW); + ram_addr_width = IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(data); + + return (1 << ram_addr_width) * (ram_ext_if_io_width / 8); +} + + + +void configure_hmc_adaptor_regs(void) +{ + uint32_t data; + uint32_t dram_io_width; + + /* Configure DDR data rate */ + dram_io_width = AGX_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0( + mmio_read_32(AGX_MPFE_IOHMC_REG_NIOSRESERVE0_OFST)); + dram_io_width = (dram_io_width & 0xFF) >> 5; + + mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_DDRIOCTRL, + AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK, + dram_io_width << AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST); + + /* Copy dram addr width from IOHMC to HMC ADP */ + data = mmio_read_32(AGX_MPFE_IOHMC_DRAMADDRW); + mmio_write_32(AGX_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data); + + /* Enable nonsecure access to DDR */ + mmio_write_32(AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT, + 0x4000000 - 1); + mmio_write_32(AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT, + 0x4000000 - 1); + mmio_write_32(AGX_SOC_NOC_FW_DDR_SCR_ENABLE, BIT(0) | BIT(8)); + + /* ECC enablement */ + data = mmio_read_32(AGX_MPFE_IOHMC_REG_CTRLCFG1); + if (data & (1 << AGX_IOHMC_CTRLCFG1_ENABLE_ECC_OFST)) { + mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL1, + AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK, + AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK); + + mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL2, + AGX_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK, + AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK); + + mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL1, + AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK, + AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK); + INFO("Scrubbing ECC\n"); + + /* ECC Scrubbing */ + zeromem(DRAM_BASE, DRAM_SIZE); + } else { + INFO("ECC is disabled.\n"); + } +} diff --git a/plat/intel/soc/agilex/soc/agilex_pinmux.c b/plat/intel/soc/agilex/soc/agilex_pinmux.c new file mode 100644 index 00000000..eff19473 --- /dev/null +++ b/plat/intel/soc/agilex/soc/agilex_pinmux.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/mmio.h> + +#include "agilex_pinmux.h" + +const uint32_t sysmgr_pinmux_array_sel[] = { + 0x00000000, 0x00000001, /* usb */ + 0x00000004, 0x00000001, + 0x00000008, 0x00000001, + 0x0000000c, 0x00000001, + 0x00000010, 0x00000001, + 0x00000014, 0x00000001, + 0x00000018, 0x00000001, + 0x0000001c, 0x00000001, + 0x00000020, 0x00000001, + 0x00000024, 0x00000001, + 0x00000028, 0x00000001, + 0x0000002c, 0x00000001, + 0x00000030, 0x00000000, /* emac0 */ + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x0000004c, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x00000000, + 0x0000005c, 0x00000000, + 0x00000060, 0x00000008, /* gpio1 */ + 0x00000064, 0x00000008, + 0x00000068, 0x00000005, /* uart0 tx */ + 0x0000006c, 0x00000005, /* uart 0 rx */ + 0x00000070, 0x00000008, /* gpio */ + 0x00000074, 0x00000008, + 0x00000078, 0x00000004, /* i2c1 */ + 0x0000007c, 0x00000004, + 0x00000080, 0x00000007, /* jtag */ + 0x00000084, 0x00000007, + 0x00000088, 0x00000007, + 0x0000008c, 0x00000007, + 0x00000090, 0x00000001, /* sdmmc data0 */ + 0x00000094, 0x00000001, + 0x00000098, 0x00000001, + 0x0000009c, 0x00000001, + 0x00000100, 0x00000001, + 0x00000104, 0x00000001, /* sdmmc.data3 */ + 0x00000108, 0x00000008, /* loan */ + 0x0000010c, 0x00000008, /* gpio */ + 0x00000110, 0x00000008, + 0x00000114, 0x00000008, /* gpio1.io21 */ + 0x00000118, 0x00000005, /* mdio0.mdio */ + 0x0000011c, 0x00000005 /* mdio0.mdc */ +}; + +const uint32_t sysmgr_pinmux_array_ctrl[] = { + 0x00000000, 0x00502c38, /* Q1_1 */ + 0x00000004, 0x00102c38, + 0x00000008, 0x00502c38, + 0x0000000c, 0x00502c38, + 0x00000010, 0x00502c38, + 0x00000014, 0x00502c38, + 0x00000018, 0x00502c38, + 0x0000001c, 0x00502c38, + 0x00000020, 0x00502c38, + 0x00000024, 0x00502c38, + 0x00000028, 0x00502c38, + 0x0000002c, 0x00502c38, + 0x00000030, 0x00102c38, /* Q2_1 */ + 0x00000034, 0x00102c38, + 0x00000038, 0x00502c38, + 0x0000003c, 0x00502c38, + 0x00000040, 0x00102c38, + 0x00000044, 0x00102c38, + 0x00000048, 0x00502c38, + 0x0000004c, 0x00502c38, + 0x00000050, 0x00102c38, + 0x00000054, 0x00102c38, + 0x00000058, 0x00502c38, + 0x0000005c, 0x00502c38, + 0x00000060, 0x00502c38, /* Q3_1 */ + 0x00000064, 0x00502c38, + 0x00000068, 0x00102c38, + 0x0000006c, 0x00502c38, + 0x000000d0, 0x00502c38, + 0x000000d4, 0x00502c38, + 0x000000d8, 0x00542c38, + 0x000000dc, 0x00542c38, + 0x000000e0, 0x00502c38, + 0x000000e4, 0x00502c38, + 0x000000e8, 0x00102c38, + 0x000000ec, 0x00502c38, + 0x000000f0, 0x00502c38, /* Q4_1 */ + 0x000000f4, 0x00502c38, + 0x000000f8, 0x00102c38, + 0x000000fc, 0x00502c38, + 0x00000100, 0x00502c38, + 0x00000104, 0x00502c38, + 0x00000108, 0x00102c38, + 0x0000010c, 0x00502c38, + 0x00000110, 0x00502c38, + 0x00000114, 0x00502c38, + 0x00000118, 0x00542c38, + 0x0000011c, 0x00102c38 +}; + +const uint32_t sysmgr_pinmux_array_fpga[] = { + 0x00000000, 0x00000000, + 0x00000004, 0x00000000, + 0x00000008, 0x00000000, + 0x0000000c, 0x00000000, + 0x00000010, 0x00000000, + 0x00000014, 0x00000000, + 0x00000018, 0x00000000, + 0x0000001c, 0x00000000, + 0x00000020, 0x00000000, + 0x00000028, 0x00000000, + 0x0000002c, 0x00000000, + 0x00000030, 0x00000000, + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x0000002a +}; + +const uint32_t sysmgr_pinmux_array_iodelay[] = { + 0x00000000, 0x00000000, + 0x00000004, 0x00000000, + 0x00000008, 0x00000000, + 0x0000000c, 0x00000000, + 0x00000010, 0x00000000, + 0x00000014, 0x00000000, + 0x00000018, 0x00000000, + 0x0000001c, 0x00000000, + 0x00000020, 0x00000000, + 0x00000024, 0x00000000, + 0x00000028, 0x00000000, + 0x0000002c, 0x00000000, + 0x00000030, 0x00000000, + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x0000004c, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x00000000, + 0x0000005c, 0x00000000, + 0x00000060, 0x00000000, + 0x00000064, 0x00000000, + 0x00000068, 0x00000000, + 0x0000006c, 0x00000000, + 0x00000070, 0x00000000, + 0x00000074, 0x00000000, + 0x00000078, 0x00000000, + 0x0000007c, 0x00000000, + 0x00000080, 0x00000000, + 0x00000084, 0x00000000, + 0x00000088, 0x00000000, + 0x0000008c, 0x00000000, + 0x00000090, 0x00000000, + 0x00000094, 0x00000000, + 0x00000098, 0x00000000, + 0x0000009c, 0x00000000, + 0x00000100, 0x00000000, + 0x00000104, 0x00000000, + 0x00000108, 0x00000000, + 0x0000010c, 0x00000000, + 0x00000110, 0x00000000, + 0x00000114, 0x00000000, + 0x00000118, 0x00000000, + 0x0000011c, 0x00000000 +}; + +void config_pinmux(handoff *hoff_ptr) +{ + unsigned int i; + + for (i = 0; i < 96; i += 2) { + mmio_write_32(AGX_PINMUX_PIN0SEL + + hoff_ptr->pinmux_sel_array[i], + hoff_ptr->pinmux_sel_array[i+1]); + } + + for (i = 0; i < 96; i += 2) { + mmio_write_32(AGX_PINMUX_IO0CTRL + + hoff_ptr->pinmux_io_array[i], + hoff_ptr->pinmux_io_array[i+1]); + } + + for (i = 0; i < 42; i += 2) { + mmio_write_32(AGX_PINMUX_PINMUX_EMAC0_USEFPGA + + hoff_ptr->pinmux_fpga_array[i], + hoff_ptr->pinmux_fpga_array[i+1]); + } + + for (i = 0; i < 96; i += 2) { + mmio_write_32(AGX_PINMUX_IO0_DELAY + + hoff_ptr->pinmux_iodelay_array[i], + hoff_ptr->pinmux_iodelay_array[i+1]); + } + +} + diff --git a/plat/intel/soc/agilex/soc/agilex_reset_manager.c b/plat/intel/soc/agilex/soc/agilex_reset_manager.c new file mode 100644 index 00000000..65d2029d --- /dev/null +++ b/plat/intel/soc/agilex/soc/agilex_reset_manager.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/mmio.h> + +#include "agilex_reset_manager.h" + +void deassert_peripheral_reset(void) +{ + mmio_clrbits_32(AGX_RSTMGR_PER1MODRST, + AGX_RSTMGR_PER1MODRST_WATCHDOG0 | + AGX_RSTMGR_PER1MODRST_WATCHDOG1 | + AGX_RSTMGR_PER1MODRST_WATCHDOG2 | + AGX_RSTMGR_PER1MODRST_WATCHDOG3 | + AGX_RSTMGR_PER1MODRST_L4SYSTIMER0 | + AGX_RSTMGR_PER1MODRST_L4SYSTIMER1 | + AGX_RSTMGR_PER1MODRST_SPTIMER0 | + AGX_RSTMGR_PER1MODRST_SPTIMER1 | + AGX_RSTMGR_PER1MODRST_I2C0 | + AGX_RSTMGR_PER1MODRST_I2C1 | + AGX_RSTMGR_PER1MODRST_I2C2 | + AGX_RSTMGR_PER1MODRST_I2C3 | + AGX_RSTMGR_PER1MODRST_I2C4 | + AGX_RSTMGR_PER1MODRST_UART0 | + AGX_RSTMGR_PER1MODRST_UART1 | + AGX_RSTMGR_PER1MODRST_GPIO0 | + AGX_RSTMGR_PER1MODRST_GPIO1); + + mmio_clrbits_32(AGX_RSTMGR_PER0MODRST, + AGX_RSTMGR_PER0MODRST_EMAC0OCP | + AGX_RSTMGR_PER0MODRST_EMAC1OCP | + AGX_RSTMGR_PER0MODRST_EMAC2OCP | + AGX_RSTMGR_PER0MODRST_USB0OCP | + AGX_RSTMGR_PER0MODRST_USB1OCP | + AGX_RSTMGR_PER0MODRST_NANDOCP | + AGX_RSTMGR_PER0MODRST_SDMMCOCP | + AGX_RSTMGR_PER0MODRST_DMAOCP); + + mmio_clrbits_32(AGX_RSTMGR_PER0MODRST, + AGX_RSTMGR_PER0MODRST_EMAC0 | + AGX_RSTMGR_PER0MODRST_EMAC1 | + AGX_RSTMGR_PER0MODRST_EMAC2 | + AGX_RSTMGR_PER0MODRST_USB0 | + AGX_RSTMGR_PER0MODRST_USB1 | + AGX_RSTMGR_PER0MODRST_NAND | + AGX_RSTMGR_PER0MODRST_SDMMC | + AGX_RSTMGR_PER0MODRST_DMA | + AGX_RSTMGR_PER0MODRST_SPIM0 | + AGX_RSTMGR_PER0MODRST_SPIM1 | + AGX_RSTMGR_PER0MODRST_SPIS0 | + AGX_RSTMGR_PER0MODRST_SPIS1 | + AGX_RSTMGR_PER0MODRST_EMACPTP | + AGX_RSTMGR_PER0MODRST_DMAIF0 | + AGX_RSTMGR_PER0MODRST_DMAIF1 | + AGX_RSTMGR_PER0MODRST_DMAIF2 | + AGX_RSTMGR_PER0MODRST_DMAIF3 | + AGX_RSTMGR_PER0MODRST_DMAIF4 | + AGX_RSTMGR_PER0MODRST_DMAIF5 | + AGX_RSTMGR_PER0MODRST_DMAIF6 | + AGX_RSTMGR_PER0MODRST_DMAIF7); + + mmio_clrbits_32(AGX_RSTMGR_BRGMODRST, + AGX_RSTMGR_BRGMODRST_MPFE); +} + +void config_hps_hs_before_warm_reset(void) +{ + uint32_t or_mask = 0; + + or_mask |= AGX_RSTMGR_HDSKEN_SDRSELFREFEN; + or_mask |= AGX_RSTMGR_HDSKEN_FPGAHSEN; + or_mask |= AGX_RSTMGR_HDSKEN_ETRSTALLEN; + or_mask |= AGX_RSTMGR_HDSKEN_L2FLUSHEN; + or_mask |= AGX_RSTMGR_HDSKEN_L3NOC_DBG; + or_mask |= AGX_RSTMGR_HDSKEN_DEBUG_L3NOC; + + mmio_setbits_32(AGX_RSTMGR_HDSKEN, or_mask); +} + diff --git a/plat/intel/soc/agilex/soc/agilex_system_manager.c b/plat/intel/soc/agilex/soc/agilex_system_manager.c new file mode 100644 index 00000000..88e895d6 --- /dev/null +++ b/plat/intel/soc/agilex/soc/agilex_system_manager.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/mmio.h> +#include <lib/utils_def.h> + +#include "agilex_system_manager.h" + +void enable_nonsecure_access(void) +{ + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_NAND_REGISTER, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_NAND_DATA, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_NAND_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_NAND_READ_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_NAND_WRITE_ECC, + DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_USB0_REGISTER, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_USB1_REGISTER, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_USB0_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_USB1_ECC, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_SPI_MASTER0, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_SPI_MASTER1, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_SPI_SLAVE0, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_SPI_SLAVE1, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_EMAC0, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_EMAC1, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_EMAC2, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_EMAC0RX_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_EMAC0TX_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_EMAC1RX_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_EMAC1TX_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_EMAC2RX_ECC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_EMAC2TX_ECC, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_SDMMC, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_SDMMC_ECC, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_GPIO0, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_GPIO1, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_I2C0, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_I2C1, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_I2C2, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_I2C3, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_I2C4, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_SP_TIMER1, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_UART0, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_PER_SCR_UART1, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_DMA_ECC, DISABLE_L4_FIREWALL); + + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_OCRAM_ECC, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_CLK_MGR, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_IO_MGR, DISABLE_L4_FIREWALL); + + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_RST_MGR, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_SYS_MGR, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_OSC0_TIMER, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_OSC1_TIMER, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_WATCHDOG0, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_WATCHDOG1, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_WATCHDOG2, DISABLE_L4_FIREWALL); + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_WATCHDOG3, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_DAP, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_L4_NOC_PROBES, DISABLE_L4_FIREWALL); + + mmio_write_32(AGX_NOC_FW_L4_SYS_SCR_L4_NOC_QOS, DISABLE_L4_FIREWALL); +} + +void enable_ns_bridge_access(void) +{ + mmio_write_32(AGX_FIREWALL_SOC2FPGA, DISABLE_BRIDGE_FIREWALL); + mmio_write_32(AGX_FIREWALL_LWSOC2FPGA, DISABLE_BRIDGE_FIREWALL); +} diff --git a/plat/intel/soc/agilex/socfpga_delay_timer.c b/plat/intel/soc/agilex/socfpga_delay_timer.c new file mode 100644 index 00000000..e74b8bd2 --- /dev/null +++ b/plat/intel/soc/agilex/socfpga_delay_timer.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <arch_helpers.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#define AGX_GLOBAL_TIMER 0xffd01000 +#define AGX_GLOBAL_TIMER_EN 0x3 + +/******************************************************************** + * The timer delay function + ********************************************************************/ +static uint32_t socfpga_get_timer_value(void) +{ + /* + * Generic delay timer implementation expects the timer to be a down + * counter. We apply bitwise NOT operator to the tick values returned + * by read_cntpct_el0() to simulate the down counter. The value is + * clipped from 64 to 32 bits. + */ + return (uint32_t)(~read_cntpct_el0()); +} + +static const timer_ops_t plat_timer_ops = { + .get_timer_value = socfpga_get_timer_value, + .clk_mult = 1, + .clk_div = PLAT_SYS_COUNTER_FREQ_IN_MHZ, +}; + +void socfpga_delay_timer_init(void) +{ + timer_init(&plat_timer_ops); + mmio_write_32(AGX_GLOBAL_TIMER, AGX_GLOBAL_TIMER_EN); +} diff --git a/plat/intel/soc/agilex/socfpga_image_load.c b/plat/intel/soc/agilex/socfpga_image_load.c new file mode 100644 index 00000000..67c02bc7 --- /dev/null +++ b/plat/intel/soc/agilex/socfpga_image_load.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/desc_image_load.h> + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/plat/intel/soc/agilex/socfpga_psci.c b/plat/intel/soc/agilex/socfpga_psci.c new file mode 100644 index 00000000..411e89bd --- /dev/null +++ b/plat/intel/soc/agilex/socfpga_psci.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/gicv2.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#include <plat/common/platform.h> + +#include "agilex_reset_manager.h" +#include "agilex_mailbox.h" + +#define AGX_RSTMGR_OFST 0xffd11000 +#define AGX_RSTMGR_MPUMODRST_OFST 0x20 + +uintptr_t *agilex_sec_entry = (uintptr_t *) PLAT_AGX_SEC_ENTRY; +uintptr_t *cpuid_release = (uintptr_t *) PLAT_CPUID_RELEASE; + +/******************************************************************************* + * plat handler called when a CPU is about to enter standby. + ******************************************************************************/ +void socfpga_cpu_standby(plat_local_state_t cpu_state) +{ + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state); + dsb(); + wfi(); +} + +/******************************************************************************* + * plat handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +int socfpga_pwr_domain_on(u_register_t mpidr) +{ + unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); + + VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); + + if (cpu_id == -1) + return PSCI_E_INTERN_FAIL; + + *cpuid_release = cpu_id; + + /* release core reset */ + mmio_setbits_32(AGX_RSTMGR_OFST + AGX_RSTMGR_MPUMODRST_OFST, + 1 << cpu_id); + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * plat handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void socfpga_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* TODO: Prevent interrupts from spuriously waking up this cpu */ + /* gicv2_cpuif_disable(); */ + + /* assert core reset */ + mmio_setbits_32(AGX_RSTMGR_OFST + AGX_RSTMGR_MPUMODRST_OFST, + 1 << cpu_id); +} + +/******************************************************************************* + * plat handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void socfpga_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + /* assert core reset */ + mmio_setbits_32(AGX_RSTMGR_OFST + AGX_RSTMGR_MPUMODRST_OFST, + 1 << cpu_id); + +} + +/******************************************************************************* + * plat handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void socfpga_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* Program the gic per-cpu distributor or re-distributor interface */ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + + /* Enable the gic cpu interface */ + gicv2_cpuif_enable(); +} + +/******************************************************************************* + * plat handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +void socfpga_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* release core reset */ + mmio_clrbits_32(AGX_RSTMGR_OFST + AGX_RSTMGR_MPUMODRST_OFST, + 1 << cpu_id); +} + +/******************************************************************************* + * plat handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 socfpga_system_off(void) +{ + wfi(); + ERROR("System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 socfpga_system_reset(void) +{ + INFO("assert Peripheral from Reset\r\n"); + + deassert_peripheral_reset(); + mailbox_reset_cold(); + + while (1) + wfi(); +} + +int socfpga_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + return PSCI_E_SUCCESS; +} + +int socfpga_validate_ns_entrypoint(unsigned long ns_entrypoint) +{ + VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint); + return PSCI_E_SUCCESS; +} + +void socfpga_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE; +} + +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +const plat_psci_ops_t socfpga_psci_pm_ops = { + .cpu_standby = socfpga_cpu_standby, + .pwr_domain_on = socfpga_pwr_domain_on, + .pwr_domain_off = socfpga_pwr_domain_off, + .pwr_domain_suspend = socfpga_pwr_domain_suspend, + .pwr_domain_on_finish = socfpga_pwr_domain_on_finish, + .pwr_domain_suspend_finish = socfpga_pwr_domain_suspend_finish, + .system_off = socfpga_system_off, + .system_reset = socfpga_system_reset, + .validate_power_state = socfpga_validate_power_state, + .validate_ns_entrypoint = socfpga_validate_ns_entrypoint, + .get_sys_suspend_power_state = socfpga_get_sys_suspend_power_state +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + /* Save warm boot entrypoint.*/ + *agilex_sec_entry = sec_entrypoint; + + *psci_ops = &socfpga_psci_pm_ops; + return 0; +} diff --git a/plat/intel/soc/agilex/socfpga_sip_svc.c b/plat/intel/soc/agilex/socfpga_sip_svc.c new file mode 100644 index 00000000..6a1c957c --- /dev/null +++ b/plat/intel/soc/agilex/socfpga_sip_svc.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <common/debug.h> +#include <common/runtime_svc.h> +#include <tools_share/uuid.h> + +#include "agilex_mailbox.h" + +/* Number of SiP Calls implemented */ +#define SIP_NUM_CALLS 0x3 + +/* Total buffer the driver can hold */ +#define FPGA_CONFIG_BUFFER_SIZE 4 + +int current_block; +int current_buffer; +int current_id = 1; +int max_blocks; +uint32_t bytes_per_block; +uint32_t blocks_submitted; +uint32_t blocks_completed; + +struct fpga_config_info { + uint32_t addr; + int size; + int size_written; + uint32_t write_requested; + int subblocks_sent; + int block_number; +}; + +/* SiP Service UUID */ +DEFINE_SVC_UUID2(intl_svc_uid, + 0xa85273b0, 0xe85a, 0x4862, 0xa6, 0x2a, + 0xfa, 0x88, 0x88, 0x17, 0x68, 0x81); + +uint64_t socfpga_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +struct fpga_config_info fpga_config_buffers[FPGA_CONFIG_BUFFER_SIZE]; + +static void intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer) +{ + uint32_t args[3]; + + while (max_blocks > 0 && buffer->size > buffer->size_written) { + if (buffer->size - buffer->size_written <= + bytes_per_block) { + args[0] = (1<<8); + args[1] = buffer->addr + buffer->size_written; + args[2] = buffer->size - buffer->size_written; + buffer->size_written += + buffer->size - buffer->size_written; + buffer->subblocks_sent++; + mailbox_send_cmd_async(0x4, + MBOX_RECONFIG_DATA, + args, 3, 0); + current_buffer++; + current_buffer %= FPGA_CONFIG_BUFFER_SIZE; + } else { + args[0] = (1<<8); + args[1] = buffer->addr + buffer->size_written; + args[2] = bytes_per_block; + buffer->size_written += bytes_per_block; + mailbox_send_cmd_async(0x4, + MBOX_RECONFIG_DATA, + args, 3, 0); + buffer->subblocks_sent++; + } + max_blocks--; + } +} + +static int intel_fpga_sdm_write_all(void) +{ + int i; + + for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) + intel_fpga_sdm_write_buffer( + &fpga_config_buffers[current_buffer]); + + return 0; +} + +uint32_t intel_mailbox_fpga_config_isdone(void) +{ + uint32_t args[2]; + uint32_t response[6]; + int status; + + status = mailbox_send_cmd(1, MBOX_RECONFIG_STATUS, args, 0, 0, + response); + + if (status < 0) + return INTEL_SIP_SMC_STATUS_ERROR; + + if (response[RECONFIG_STATUS_STATE] && + response[RECONFIG_STATUS_STATE] != MBOX_CFGSTAT_STATE_CONFIG) + return INTEL_SIP_SMC_STATUS_ERROR; + + if (!(response[RECONFIG_STATUS_PIN_STATUS] & PIN_STATUS_NSTATUS)) + return INTEL_SIP_SMC_STATUS_ERROR; + + if (response[RECONFIG_STATUS_SOFTFUNC_STATUS] & + SOFTFUNC_STATUS_SEU_ERROR) + return INTEL_SIP_SMC_STATUS_ERROR; + + if ((response[RECONFIG_STATUS_SOFTFUNC_STATUS] & + SOFTFUNC_STATUS_CONF_DONE) && + (response[RECONFIG_STATUS_SOFTFUNC_STATUS] & + SOFTFUNC_STATUS_INIT_DONE)) + return INTEL_SIP_SMC_STATUS_OK; + + return INTEL_SIP_SMC_STATUS_ERROR; +} + +static int mark_last_buffer_xfer_completed(uint32_t *buffer_addr_completed) +{ + int i; + + for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + if (fpga_config_buffers[i].block_number == current_block) { + fpga_config_buffers[i].subblocks_sent--; + if (fpga_config_buffers[i].subblocks_sent == 0 + && fpga_config_buffers[i].size <= + fpga_config_buffers[i].size_written) { + fpga_config_buffers[i].write_requested = 0; + current_block++; + *buffer_addr_completed = + fpga_config_buffers[i].addr; + return 0; + } + } + } + + return -1; +} + +unsigned int address_in_ddr(uint32_t *addr) +{ + if (((unsigned long long)addr > DRAM_BASE) && + ((unsigned long long)addr < DRAM_BASE + DRAM_SIZE)) + return 0; + + return -1; +} + +int intel_fpga_config_completed_write(uint32_t *completed_addr, + uint32_t *count) +{ + uint32_t status = INTEL_SIP_SMC_STATUS_OK; + *count = 0; + int resp_len = 0; + uint32_t resp[5]; + int all_completed = 1; + int count_check = 0; + + if (address_in_ddr(completed_addr) != 0 || address_in_ddr(count) != 0) + return INTEL_SIP_SMC_STATUS_ERROR; + + for (count_check = 0; count_check < 3; count_check++) + if (address_in_ddr(&completed_addr[*count + count_check]) != 0) + return INTEL_SIP_SMC_STATUS_ERROR; + + resp_len = mailbox_read_response(0x4, resp); + + while (resp_len >= 0 && *count < 3) { + max_blocks++; + if (mark_last_buffer_xfer_completed( + &completed_addr[*count]) == 0) + *count = *count + 1; + else + break; + resp_len = mailbox_read_response(0x4, resp); + } + + if (*count <= 0) { + if (resp_len != MBOX_NO_RESPONSE && + resp_len != MBOX_TIMEOUT && resp_len != 0) { + return INTEL_SIP_SMC_STATUS_ERROR; + } + + *count = 0; + } + + intel_fpga_sdm_write_all(); + + if (*count > 0) + status = INTEL_SIP_SMC_STATUS_OK; + else if (*count == 0) + status = INTEL_SIP_SMC_STATUS_BUSY; + + for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + if (fpga_config_buffers[i].write_requested != 0) { + all_completed = 0; + break; + } + } + + if (all_completed == 1) + return INTEL_SIP_SMC_STATUS_OK; + + return status; +} + +int intel_fpga_config_start(uint32_t config_type) +{ + uint32_t response[3]; + int status = 0; + + status = mailbox_send_cmd(2, MBOX_RECONFIG, 0, 0, 0, + response); + + if (status < 0) + return status; + + max_blocks = response[0]; + bytes_per_block = response[1]; + + for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + fpga_config_buffers[i].size = 0; + fpga_config_buffers[i].size_written = 0; + fpga_config_buffers[i].addr = 0; + fpga_config_buffers[i].write_requested = 0; + fpga_config_buffers[i].block_number = 0; + fpga_config_buffers[i].subblocks_sent = 0; + } + + blocks_submitted = 0; + current_block = 0; + current_buffer = 0; + + return 0; +} + + +uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size) +{ + int i = 0; + uint32_t status = INTEL_SIP_SMC_STATUS_OK; + + if (mem < DRAM_BASE || mem > DRAM_BASE + DRAM_SIZE) + status = INTEL_SIP_SMC_STATUS_REJECTED; + + if (mem + size > DRAM_BASE + DRAM_SIZE) + status = INTEL_SIP_SMC_STATUS_REJECTED; + + for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + if (!fpga_config_buffers[i].write_requested) { + fpga_config_buffers[i].addr = mem; + fpga_config_buffers[i].size = size; + fpga_config_buffers[i].size_written = 0; + fpga_config_buffers[i].write_requested = 1; + fpga_config_buffers[i].block_number = + blocks_submitted++; + fpga_config_buffers[i].subblocks_sent = 0; + break; + } + } + + + if (i == FPGA_CONFIG_BUFFER_SIZE) { + status = INTEL_SIP_SMC_STATUS_REJECTED; + return status; + } else if (i == FPGA_CONFIG_BUFFER_SIZE - 1) { + status = INTEL_SIP_SMC_STATUS_BUSY; + } + + intel_fpga_sdm_write_all(); + + return status; +} + +/* + * This function is responsible for handling all SiP calls from the NS world + */ + +uintptr_t sip_smc_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + uint32_t status = INTEL_SIP_SMC_STATUS_OK; + uint32_t completed_addr[3]; + uint32_t count = 0; + + switch (smc_fid) { + case SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, intl_svc_uid); + break; + case INTEL_SIP_SMC_FPGA_CONFIG_ISDONE: + status = intel_mailbox_fpga_config_isdone(); + SMC_RET4(handle, status, 0, 0, 0); + break; + case INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM: + SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK, + INTEL_SIP_SMC_FPGA_CONFIG_ADDR, + INTEL_SIP_SMC_FPGA_CONFIG_SIZE - + INTEL_SIP_SMC_FPGA_CONFIG_ADDR); + break; + case INTEL_SIP_SMC_FPGA_CONFIG_START: + status = intel_fpga_config_start(x1); + SMC_RET4(handle, status, 0, 0, 0); + break; + case INTEL_SIP_SMC_FPGA_CONFIG_WRITE: + status = intel_fpga_config_write(x1, x2); + SMC_RET4(handle, status, 0, 0, 0); + break; + case INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE: + status = intel_fpga_config_completed_write(completed_addr, + &count); + switch (count) { + case 1: + SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, + completed_addr[0], 0, 0); + break; + case 2: + SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, + completed_addr[0], + completed_addr[1], 0); + break; + case 3: + SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, + completed_addr[0], + completed_addr[1], + completed_addr[2]); + break; + case 0: + SMC_RET4(handle, status, 0, 0, 0); + break; + default: + SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR); + } + break; + + default: + return socfpga_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +DECLARE_RT_SVC( + agilex_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + sip_smc_handler +); + +DECLARE_RT_SVC( + agilex_sip_svc_std, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_YIELD, + NULL, + sip_smc_handler +); diff --git a/plat/intel/soc/agilex/socfpga_storage.c b/plat/intel/soc/agilex/socfpga_storage.c new file mode 100644 index 00000000..76dd81f7 --- /dev/null +++ b/plat/intel/soc/agilex/socfpga_storage.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <common/debug.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/io/io_block.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_fip.h> +#include <drivers/io/io_memmap.h> +#include <drivers/io/io_storage.h> +#include <drivers/mmc.h> +#include <drivers/partition/partition.h> +#include <lib/mmio.h> +#include <tools_share/firmware_image_package.h> + +#include "agilex_private.h" + +#define PLAT_FIP_BASE (0) +#define PLAT_FIP_MAX_SIZE (0x1000000) +#define PLAT_MMC_DATA_BASE (0xffe3c000) +#define PLAT_MMC_DATA_SIZE (0x2000) +#define PLAT_QSPI_DATA_BASE (0x3C00000) +#define PLAT_QSPI_DATA_SIZE (0x1000000) + + +static const io_dev_connector_t *fip_dev_con; +static const io_dev_connector_t *boot_dev_con; + +static uintptr_t fip_dev_handle; +static uintptr_t boot_dev_handle; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +uintptr_t a2_lba_offset; +const char a2[] = {0xa2, 0x0}; + +static const io_block_spec_t gpt_block_spec = { + .offset = 0, + .length = MMC_BLOCK_SIZE +}; + +static int check_fip(const uintptr_t spec); +static int check_dev(const uintptr_t spec); + +static io_block_dev_spec_t boot_dev_spec; +static int (*register_io_dev)(const io_dev_connector_t **); + +static io_block_spec_t fip_spec = { + .offset = PLAT_FIP_BASE, + .length = PLAT_FIP_MAX_SIZE, +}; + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &boot_dev_handle, + (uintptr_t)&fip_spec, + check_dev + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&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 + }, + [GPT_IMAGE_ID] = { + &boot_dev_handle, + (uintptr_t) &gpt_block_spec, + check_dev + }, +}; + +static int check_dev(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(boot_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(boot_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; + + 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) + io_close(local_image_handle); + } + return result; +} + +void socfpga_io_setup(int boot_source) +{ + int result; + + switch (boot_source) { + case BOOT_SOURCE_SDMMC: + register_io_dev = ®ister_io_dev_block; + boot_dev_spec.buffer.offset = PLAT_MMC_DATA_BASE; + boot_dev_spec.buffer.length = MMC_BLOCK_SIZE; + boot_dev_spec.ops.read = mmc_read_blocks; + boot_dev_spec.ops.write = mmc_write_blocks; + boot_dev_spec.block_size = MMC_BLOCK_SIZE; + break; + + case BOOT_SOURCE_QSPI: + register_io_dev = ®ister_io_dev_memmap; + fip_spec.offset = fip_spec.offset + PLAT_QSPI_DATA_BASE; + break; + + default: + ERROR("Unsupported boot source\n"); + panic(); + break; + } + + result = (*register_io_dev)(&boot_dev_con); + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec, + &boot_dev_handle); + assert(result == 0); + + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); + assert(result == 0); + + if (boot_source == BOOT_SOURCE_SDMMC) { + partition_init(GPT_IMAGE_ID); + fip_spec.offset = get_partition_entry(a2)->start; + } + + (void)result; +} + +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; +} diff --git a/plat/intel/soc/agilex/socfpga_topology.c b/plat/intel/soc/agilex/socfpga_topology.c new file mode 100644 index 00000000..ca1a91e3 --- /dev/null +++ b/plat/intel/soc/agilex/socfpga_topology.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <platform_def.h> +#include <lib/psci/psci.h> + +static const unsigned char plat_power_domain_tree_desc[] = {1, 4}; + +/******************************************************************************* + * This function returns the default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_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_MAX_CPUS_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} + diff --git a/plat/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c index dd23e63e..ad81b169 100644 --- a/plat/mediatek/mt8173/bl31_plat_setup.c +++ b/plat/mediatek/mt8173/bl31_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,6 +8,7 @@ #include <common/bl_common.h> #include <common/debug.h> +#include <common/desc_image_load.h> #include <drivers/console.h> #include <drivers/generic_delay_timer.h> #include <lib/mmio.h> @@ -79,6 +80,7 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) entry_point_info_t *next_image_info; next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); /* None of the images on this platform can have 0x0 as the entrypoint */ if (next_image_info->pc) @@ -98,18 +100,11 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { - struct mtk_bl31_params *arg_from_bl2 = (struct mtk_bl31_params *)arg0; - console_init(MT8173_UART0_BASE, MT8173_UART_CLOCK, MT8173_BAUDRATE); VERBOSE("bl31_setup\n"); - assert(arg_from_bl2 != NULL); - assert(arg_from_bl2->h.type == PARAM_BL31); - assert(arg_from_bl2->h.version >= VERSION_1); - - bl32_ep_info = *arg_from_bl2->bl32_ep_info; - bl33_ep_info = *arg_from_bl2->bl33_ep_info; + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); } /******************************************************************************* diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk index 0726efe4..24e4ec65 100644 --- a/plat/mediatek/mt8173/platform.mk +++ b/plat/mediatek/mt8173/platform.mk @@ -23,7 +23,8 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ plat/arm/common/arm_gicv2.c \ plat/common/plat_gicv2.c -BL31_SOURCES += drivers/arm/cci/cci.c \ +BL31_SOURCES += common/desc_image_load.c \ + drivers/arm/cci/cci.c \ drivers/arm/gic/common/gic_common.c \ drivers/arm/gic/v2/gicv2_main.c \ drivers/arm/gic/v2/gicv2_helpers.c \ diff --git a/plat/mediatek/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c index b451189d..e623e96a 100644 --- a/plat/mediatek/mt8183/bl31_plat_setup.c +++ b/plat/mediatek/mt8183/bl31_plat_setup.c @@ -7,6 +7,7 @@ #include <assert.h> #include <arch_helpers.h> #include <common/bl_common.h> +#include <common/desc_image_load.h> #include <plat/common/common_def.h> #include <drivers/console.h> #include <common/debug.h> @@ -50,6 +51,7 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) entry_point_info_t *next_image_info; next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); /* None of the images on this platform can have 0x0 as the entrypoint */ if (next_image_info->pc) @@ -69,19 +71,13 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { - struct mtk_bl31_params *arg_from_bl2 = (struct mtk_bl31_params *)arg0; static console_16550_t console; console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console); NOTICE("MT8183 bl31_setup\n"); - assert(arg_from_bl2 != NULL); - assert(arg_from_bl2->h.type == PARAM_BL31); - assert(arg_from_bl2->h.version >= VERSION_1); - - bl32_ep_info = *arg_from_bl2->bl32_ep_info; - bl33_ep_info = *arg_from_bl2->bl33_ep_info; + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); } diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk index 8c8e2fe9..f0a598a3 100644 --- a/plat/mediatek/mt8183/platform.mk +++ b/plat/mediatek/mt8183/platform.mk @@ -16,7 +16,8 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ plat/common/plat_psci_common.c \ plat/common/aarch64/crash_console_helpers.S -BL31_SOURCES += drivers/arm/cci/cci.c \ +BL31_SOURCES += common/desc_image_load.c \ + drivers/arm/cci/cci.c \ drivers/arm/gic/common/gic_common.c \ drivers/arm/gic/v3/arm_gicv3_common.c \ drivers/arm/gic/v3/gicv3_helpers.c \ diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c index 18f8dd91..a13ee495 100644 --- a/plat/rockchip/common/bl31_plat_setup.c +++ b/plat/rockchip/common/bl31_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -10,6 +10,7 @@ #include <common/bl_common.h> #include <common/debug.h> +#include <common/desc_image_load.h> #include <drivers/console.h> #include <drivers/generic_delay_timer.h> #include <drivers/ti/uart/uart_16550.h> @@ -32,6 +33,7 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) entry_point_info_t *next_image_info; next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); /* None of the images on this platform can have 0x0 as the entrypoint */ if (next_image_info->pc) @@ -41,7 +43,7 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) } #pragma weak params_early_setup -void params_early_setup(void *plat_param_from_bl2) +void params_early_setup(u_register_t plat_param_from_bl2) { } @@ -57,10 +59,8 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { static console_16550_t console; - struct rockchip_bl31_params *arg_from_bl2 = (struct rockchip_bl31_params *) arg0; - void *plat_params_from_bl2 = (void *) arg1; - params_early_setup(plat_params_from_bl2); + params_early_setup(arg1); #if COREBOOT if (coreboot_serial.type) @@ -75,14 +75,7 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, VERBOSE("bl31_setup\n"); - /* Passing a NULL context is a critical programming error */ - assert(arg_from_bl2); - - assert(arg_from_bl2->h.type == PARAM_BL31); - assert(arg_from_bl2->h.version >= VERSION_1); - - bl32_ep_info = *arg_from_bl2->bl32_ep_info; - bl33_ep_info = *arg_from_bl2->bl33_ep_info; + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); } /******************************************************************************* diff --git a/plat/rockchip/common/include/plat_params.h b/plat/rockchip/common/include/plat_params.h index 1ec02f55..95b850f5 100644 --- a/plat/rockchip/common/include/plat_params.h +++ b/plat/rockchip/common/include/plat_params.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,90 +9,6 @@ #include <stdint.h> -/* - * We defined several plat parameter structs for BL2 to pass platform related - * parameters to Rockchip BL31 platform code. All plat parameters start with - * a common header, which has a type field to indicate the parameter type, and - * a next pointer points to next parameter. If the parameter is the last one in - * the list, next pointer will points to NULL. After the header comes the - * variable-sized members that describe the parameter. The picture below shows - * how the parameters are kept in memory. - * - * head of list ---> +----------------+ --+ - * | type | | - * +----------------+ |--> struct bl31_plat_param - * +----| next | | - * | +----------------+ --+ - * | | parameter data | - * | +----------------+ - * | - * +--> +----------------+ --+ - * | type | | - * +----------------+ |--> struct bl31_plat_param - * NULL <---| next | | - * +----------------+ --+ - * | parameter data | - * +----------------+ - * - * Note: The SCTLR_EL3.A bit (Alignment fault check enable) of ARM TF is set, - * so be sure each parameter struct starts on 64-bit aligned address. If not, - * alignment fault will occur during accessing its data member. - */ - -#define BL31_GPIO_DIR_OUT 0 -#define BL31_GPIO_DIR_IN 1 - -#define BL31_GPIO_LEVEL_LOW 0 -#define BL31_GPIO_LEVEL_HIGH 1 - -#define BL31_GPIO_PULL_NONE 0 -#define BL31_GPIO_PULL_UP 1 -#define BL31_GPIO_PULL_DOWN 2 - -/* param type */ -enum { - PARAM_NONE = 0, - PARAM_RESET, - PARAM_POWEROFF, - PARAM_SUSPEND_GPIO, - PARAM_SUSPEND_APIO, - PARAM_COREBOOT_TABLE, -}; - -struct apio_info { - uint8_t apio1 : 1; - uint8_t apio2 : 1; - uint8_t apio3 : 1; - uint8_t apio4 : 1; - uint8_t apio5 : 1; -}; - -struct gpio_info { - uint8_t polarity; - uint8_t direction; - uint8_t pull_mode; - uint32_t index; -}; - -/* common header for all plat parameter type */ -struct bl31_plat_param { - uint64_t type; - void *next; -}; - -struct bl31_gpio_param { - struct bl31_plat_param h; - struct gpio_info gpio; -}; - -struct bl31_apio_param { - struct bl31_plat_param h; - struct apio_info apio; -}; - -struct bl31_u64_param { - struct bl31_plat_param h; - uint64_t value; -}; +#include <export/plat/rockchip/common/plat_params_exp.h> #endif /* PLAT_PARAMS_H */ diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index c0ebefc4..66b61850 100644 --- a/plat/rockchip/common/include/plat_private.h +++ b/plat/rockchip/common/include/plat_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,6 +14,7 @@ #include <lib/psci/psci.h> #include <lib/xlat_tables/xlat_tables.h> #include <lib/mmio.h> +#include <plat_params.h> #define __sramdata __attribute__((section(".sram.data"))) #define __sramconst __attribute__((section(".sram.rodata"))) @@ -30,15 +31,6 @@ 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; -struct rockchip_bl31_params { - param_header_t h; - image_info_t *bl31_image_info; - entry_point_info_t *bl32_ep_info; - image_info_t *bl32_image_info; - entry_point_info_t *bl33_ep_info; - image_info_t *bl33_image_info; -}; - /****************************************************************************** * The register have write-mask bits, it is mean, if you want to set the bits, * you needs set the write-mask bits at the same time, @@ -94,7 +86,7 @@ void plat_cci_disable(void); void plat_delay_timer_init(void); -void params_early_setup(void *plat_params_from_bl2); +void params_early_setup(u_register_t plat_params_from_bl2); void plat_rockchip_gic_driver_init(void); void plat_rockchip_gic_init(void); @@ -108,10 +100,10 @@ uintptr_t plat_get_sec_entrypoint(void); void platform_cpu_warmboot(void); -struct gpio_info *plat_get_rockchip_gpio_reset(void); -struct gpio_info *plat_get_rockchip_gpio_poweroff(void); -struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count); -struct apio_info *plat_get_rockchip_suspend_apio(void); +struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void); +struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void); +struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count); +struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void); void plat_rockchip_gpio_init(void); void plat_rockchip_save_gpio(void); void plat_rockchip_restore_gpio(void); diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c index 8a743bfe..d0fea4ff 100644 --- a/plat/rockchip/common/params_setup.c +++ b/plat/rockchip/common/params_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,6 +8,7 @@ #include <errno.h> #include <string.h> +#include <lib/bl_aux_params/bl_aux_params.h> #include <common/bl_common.h> #include <common/debug.h> #include <drivers/console.h> @@ -20,14 +21,11 @@ #include <plat_params.h> #include <plat_private.h> -static struct gpio_info param_reset; -static struct gpio_info param_poweroff; -static struct bl31_apio_param param_apio; -static struct gpio_info *rst_gpio; -static struct gpio_info *poweroff_gpio; -static struct gpio_info suspend_gpio[10]; +static struct bl_aux_gpio_info rst_gpio; +static struct bl_aux_gpio_info poweroff_gpio; +static struct bl_aux_gpio_info suspend_gpio[10]; uint32_t suspend_gpio_cnt; -static struct apio_info *suspend_apio; +static struct bl_aux_rk_apio_info suspend_apio; static uint32_t rk_uart_base = PLAT_RK_UART_BASE; uint32_t rockchip_get_uart_base(void) @@ -36,7 +34,7 @@ uint32_t rockchip_get_uart_base(void) } #if COREBOOT -static int dt_process_fdt(void *blob) +static int dt_process_fdt(u_register_t param_from_bl2) { return -ENODEV; } @@ -105,12 +103,12 @@ static void plat_rockchip_dt_process_fdt_uart(void *fdt) rk_uart_base = uart_base; } -static int dt_process_fdt(void *blob) +static int dt_process_fdt(u_register_t param_from_bl2) { void *fdt = plat_get_fdt(); int ret; - ret = fdt_open_into(blob, fdt, 0x10000); + ret = fdt_open_into((void *)param_from_bl2, fdt, 0x10000); if (ret < 0) return ret; @@ -120,33 +118,56 @@ static int dt_process_fdt(void *blob) } #endif -struct gpio_info *plat_get_rockchip_gpio_reset(void) +struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void) { - return rst_gpio; + return &rst_gpio; } -struct gpio_info *plat_get_rockchip_gpio_poweroff(void) +struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void) { - return poweroff_gpio; + return &poweroff_gpio; } -struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count) +struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count) { *count = suspend_gpio_cnt; return &suspend_gpio[0]; } -struct apio_info *plat_get_rockchip_suspend_apio(void) +struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void) { - return suspend_apio; + return &suspend_apio; } -void params_early_setup(void *plat_param_from_bl2) +static bool rk_aux_param_handler(struct bl_aux_param_header *param) { - struct bl31_plat_param *bl2_param; - struct bl31_gpio_param *gpio_param; + /* Store platform parameters for later processing if needed. */ + switch (param->type) { + case BL_AUX_PARAM_RK_RESET_GPIO: + rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio; + return true; + case BL_AUX_PARAM_RK_POWEROFF_GPIO: + poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio; + return true; + case BL_AUX_PARAM_RK_SUSPEND_GPIO: + if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) { + ERROR("Exceeded the supported suspend GPIO number.\n"); + return true; + } + suspend_gpio[suspend_gpio_cnt++] = + ((struct bl_aux_param_gpio *)param)->gpio; + return true; + case BL_AUX_PARAM_RK_SUSPEND_APIO: + suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio; + return true; + } + return false; +} + +void params_early_setup(u_register_t plat_param_from_bl2) +{ /* * Test if this is a FDT passed as a platform-specific parameter * block. @@ -154,49 +175,5 @@ void params_early_setup(void *plat_param_from_bl2) if (!dt_process_fdt(plat_param_from_bl2)) return; - /* keep plat parameters for later processing if need */ - bl2_param = (struct bl31_plat_param *)plat_param_from_bl2; - while (bl2_param) { - switch (bl2_param->type) { - case PARAM_RESET: - gpio_param = (struct bl31_gpio_param *)bl2_param; - memcpy(¶m_reset, &gpio_param->gpio, - sizeof(struct gpio_info)); - rst_gpio = ¶m_reset; - break; - case PARAM_POWEROFF: - gpio_param = (struct bl31_gpio_param *)bl2_param; - memcpy(¶m_poweroff, &gpio_param->gpio, - sizeof(struct gpio_info)); - poweroff_gpio = ¶m_poweroff; - break; - case PARAM_SUSPEND_GPIO: - if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) { - ERROR("exceed support suspend gpio number\n"); - break; - } - gpio_param = (struct bl31_gpio_param *)bl2_param; - memcpy(&suspend_gpio[suspend_gpio_cnt], - &gpio_param->gpio, - sizeof(struct gpio_info)); - suspend_gpio_cnt++; - break; - case PARAM_SUSPEND_APIO: - memcpy(¶m_apio, bl2_param, - sizeof(struct bl31_apio_param)); - suspend_apio = ¶m_apio.apio; - break; -#if COREBOOT - case PARAM_COREBOOT_TABLE: - coreboot_table_setup((void *) - ((struct bl31_u64_param *)bl2_param)->value); - break; -#endif - default: - ERROR("not expected type found %lld\n", - bl2_param->type); - break; - } - bl2_param = bl2_param->next; - } + bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler); } diff --git a/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S new file mode 100644 index 00000000..6cea2eaa --- /dev/null +++ b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> +#include <cpus_on_fixed_addr.h> + + .globl sys_sleep_flag_sram + .globl pmu_cpuson_entrypoint + + .macro pmusram_entry_func _name + .section .pmusram.entry, "ax" + .type \_name, %function + .cfi_startproc + \_name: + .endm + +pmusram_entry_func pmu_cpuson_entrypoint + adr x5, sys_sleep_flag_sram + ldr w2, [x5, #PSRAM_DT_PM_FLAG] + + tbz w2, #PM_WARM_BOOT_SHT, sys_resume_sp + ldr x1, =platform_cpu_warmboot + br x1 +sys_resume_sp: + adr x5, sys_sleep_flag_sram + ldr x1, [x5, #PSRAM_DT_SP] + mov sp, x1 +ddr_resume: + ldr x1, [x5, #PSRAM_DT_DDR_FUNC] + cmp x1, #0 + b.eq sys_resume + blr x1 +sys_resume: + ldr x1, =bl31_warm_entrypoint + br x1 +endfunc pmu_cpuson_entrypoint + + .section .pmusram.data, "a" + .align 3 +sys_sleep_flag_sram: + .rept PSRAM_DT_SIZE_WORDS + .word 0 + .endr diff --git a/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h new file mode 100644 index 00000000..b22ddc29 --- /dev/null +++ b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CPU_ON_FIXED_ADDR_H__ +#define __CPU_ON_FIXED_ADDR_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_PM_FLAG 0x20 +#define PSRAM_DT_END 0x24 + +/* reserve 4 byte */ +#define PSRAM_DT_END_RES4 (PSRAM_DT_END + 4) + +#define PSRAM_DT_SIZE_WORDS (PSRAM_DT_END_RES4 / 4) + +#define PM_WARM_BOOT_SHT 0 +#define PM_WARM_BOOT_BIT (1 << PM_WARM_BOOT_SHT) + +#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; + uint32_t pm_flag; +}; + +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); + +extern void *sys_sleep_flag_sram; + +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/plat/rockchip/common/sp_min_plat_setup.c b/plat/rockchip/common/sp_min_plat_setup.c index 7cdbaba1..7b1a0b58 100644 --- a/plat/rockchip/common/sp_min_plat_setup.c +++ b/plat/rockchip/common/sp_min_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,6 +11,7 @@ #include <arch_helpers.h> #include <common/bl_common.h> #include <common/debug.h> +#include <common/desc_image_load.h> #include <drivers/console.h> #include <drivers/generic_delay_timer.h> #include <drivers/ti/uart/uart_16550.h> @@ -40,7 +41,7 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) } #pragma weak params_early_setup -void params_early_setup(void *plat_param_from_bl2) +void params_early_setup(u_register_t plat_param_from_bl2) { } @@ -53,10 +54,8 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { static console_16550_t console; - struct rockchip_bl31_params *arg_from_bl2 = (struct rockchip_bl31_params *) arg0; - void *plat_params_from_bl2 = (void *) arg1; - params_early_setup(plat_params_from_bl2); + params_early_setup(arg1); #if COREBOOT if (coreboot_serial.type) @@ -70,13 +69,7 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, #endif VERBOSE("sp_min_setup\n"); - /* Passing a NULL context is a critical programming error */ - assert(arg_from_bl2); - - assert(arg_from_bl2->h.type == PARAM_BL31); - assert(arg_from_bl2->h.version >= VERSION_1); - - bl33_ep_info = *arg_from_bl2->bl33_ep_info; + bl31_params_parse_helper(arg0, NULL, &bl33_ep_info); } /******************************************************************************* diff --git a/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 00000000..a757621e --- /dev/null +++ b/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + +.globl clst_warmboot_data + +.macro func_rockchip_clst_warmboot +.endm + +.macro rockchip_clst_warmboot_data +clst_warmboot_data: + .rept PLATFORM_CLUSTER_COUNT + .word 0 + .endr +.endm diff --git a/plat/rockchip/px30/drivers/pmu/pmu.c b/plat/rockchip/px30/drivers/pmu/pmu.c new file mode 100644 index 00000000..a5ed7664 --- /dev/null +++ b/plat/rockchip/px30/drivers/pmu/pmu.c @@ -0,0 +1,1070 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <bl31/bl31.h> +#include <common/debug.h> +#include <drivers/console.h> +#include <drivers/delay_timer.h> +#include <lib/bakery_lock.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <cpus_on_fixed_addr.h> +#include <plat_private.h> +#include <pmu.h> +#include <px30_def.h> +#include <soc.h> + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); +#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock) +#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock) +#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock) + +static struct psram_data_t *psram_boot_cfg = + (struct psram_data_t *)&sys_sleep_flag_sram; + +/* + * There are two ways to powering on or off on core. + * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, + * it is core_pwr_pd mode + * 2) Enable the core power manage in PMU_CORE_PM_CON reg, + * then, if the core enter into wfi, it power domain will be + * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode + * so we need core_pm_cfg_info to distinguish which method be used now. + */ + +static uint32_t cores_pd_cfg_info[PLATFORM_CORE_COUNT] +#if USE_COHERENT_MEM +__attribute__ ((section("tzfw_coherent_mem"))) +#endif +; + +struct px30_sleep_ddr_data { + uint32_t clk_sel0; + uint32_t cru_mode_save; + uint32_t cru_pmu_mode_save; + uint32_t ddrc_hwlpctl; + uint32_t ddrc_pwrctrl; + uint32_t ddrgrf_con0; + uint32_t ddrgrf_con1; + uint32_t ddrstdby_con0; + uint32_t gpio0b_iomux; + uint32_t gpio0c_iomux; + uint32_t pmu_pwrmd_core_l; + uint32_t pmu_pwrmd_core_h; + uint32_t pmu_pwrmd_cmm_l; + uint32_t pmu_pwrmd_cmm_h; + uint32_t pmu_wkup_cfg2_l; + uint32_t pmu_cru_clksel_con0; + uint32_t pmugrf_soc_con0; + uint32_t pmusgrf_soc_con0; + uint32_t pmic_slp_iomux; + uint32_t pgrf_pvtm_con[2]; + uint32_t cru_clk_gate[CRU_CLKGATES_CON_CNT]; + uint32_t cru_pmu_clk_gate[CRU_PMU_CLKGATE_CON_CNT]; + uint32_t cru_plls_con_save[END_PLL_ID][PLL_CON_CNT]; + uint32_t cpu_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t gpu_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_128m_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_rd_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_wr_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_m1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vip_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t rga_rd_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t rga_wr_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vop_m0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vop_m1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vpu_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vpu_r128_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t dcf_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t dmac_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t crypto_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t gmac_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t emmc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t nand_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sdio_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sfc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sdmmc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_host_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_otg_qos[CPU_AXI_QOS_NUM_REGS]; +}; + +static struct px30_sleep_ddr_data ddr_data +#if USE_COHERENT_MEM +__attribute__ ((section("tzfw_coherent_mem"))) +#endif +; + +static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) +{ + assert(cpu_id < PLATFORM_CORE_COUNT); + return cores_pd_cfg_info[cpu_id]; +} + +static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) +{ + assert(cpu_id < PLATFORM_CORE_COUNT); + cores_pd_cfg_info[cpu_id] = value; +#if !USE_COHERENT_MEM + flush_dcache_range((uintptr_t)&cores_pd_cfg_info[cpu_id], + sizeof(uint32_t)); +#endif +} + +static inline uint32_t pmu_power_domain_st(uint32_t pd) +{ + return mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd) ? + pmu_pd_off : + pmu_pd_on; +} + +static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state) +{ + uint32_t loop = 0; + int ret = 0; + + rockchip_pd_lock_get(); + + mmio_write_32(PMU_BASE + PMU_PWRDN_CON, + BITS_WITH_WMASK(pd_state, 0x1, pd)); + dsb(); + + while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) { + udelay(1); + loop++; + } + + if (pmu_power_domain_st(pd) != pd_state) { + WARN("%s: %d, %d, error!\n", __func__, pd, pd_state); + ret = -EINVAL; + } + + rockchip_pd_lock_rls(); + + return ret; +} + +static inline uint32_t pmu_bus_idle_st(uint32_t bus) +{ + return !!((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus)) && + (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus + 16))); +} + +static void pmu_bus_idle_req(uint32_t bus, uint32_t state) +{ + uint32_t wait_cnt = 0; + + mmio_write_32(PMU_BASE + PMU_BUS_IDLE_REQ, + BITS_WITH_WMASK(state, 0x1, bus)); + + while (pmu_bus_idle_st(bus) != state && + wait_cnt < BUS_IDLE_LOOP) { + udelay(1); + wait_cnt++; + } + + if (pmu_bus_idle_st(bus) != state) + WARN("%s:idle_st=0x%x, bus_id=%d\n", + __func__, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST), bus); +} + +static void qos_save(void) +{ + /* scu powerdomain will power off, so cpu qos should be saved */ + SAVE_QOS(ddr_data.cpu_qos, CPU); + + if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) + SAVE_QOS(ddr_data.gpu_qos, GPU); + if (pmu_power_domain_st(PD_VI) == pmu_pd_on) { + SAVE_QOS(ddr_data.isp_128m_qos, ISP_128M); + SAVE_QOS(ddr_data.isp_rd_qos, ISP_RD); + SAVE_QOS(ddr_data.isp_wr_qos, ISP_WR); + SAVE_QOS(ddr_data.isp_m1_qos, ISP_M1); + SAVE_QOS(ddr_data.vip_qos, VIP); + } + if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { + SAVE_QOS(ddr_data.rga_rd_qos, RGA_RD); + SAVE_QOS(ddr_data.rga_wr_qos, RGA_WR); + SAVE_QOS(ddr_data.vop_m0_qos, VOP_M0); + SAVE_QOS(ddr_data.vop_m1_qos, VOP_M1); + } + if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) { + SAVE_QOS(ddr_data.vpu_qos, VPU); + SAVE_QOS(ddr_data.vpu_r128_qos, VPU_R128); + } + if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) { + SAVE_QOS(ddr_data.emmc_qos, EMMC); + SAVE_QOS(ddr_data.nand_qos, NAND); + SAVE_QOS(ddr_data.sdio_qos, SDIO); + SAVE_QOS(ddr_data.sfc_qos, SFC); + } + if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) + SAVE_QOS(ddr_data.gmac_qos, GMAC); + if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on) + SAVE_QOS(ddr_data.crypto_qos, CRYPTO); + if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on) + SAVE_QOS(ddr_data.sdmmc_qos, SDMMC); + if (pmu_power_domain_st(PD_USB) == pmu_pd_on) { + SAVE_QOS(ddr_data.usb_host_qos, USB_HOST); + SAVE_QOS(ddr_data.usb_otg_qos, USB_OTG); + } +} + +static void qos_restore(void) +{ + RESTORE_QOS(ddr_data.cpu_qos, CPU); + + if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) + RESTORE_QOS(ddr_data.gpu_qos, GPU); + if (pmu_power_domain_st(PD_VI) == pmu_pd_on) { + RESTORE_QOS(ddr_data.isp_128m_qos, ISP_128M); + RESTORE_QOS(ddr_data.isp_rd_qos, ISP_RD); + RESTORE_QOS(ddr_data.isp_wr_qos, ISP_WR); + RESTORE_QOS(ddr_data.isp_m1_qos, ISP_M1); + RESTORE_QOS(ddr_data.vip_qos, VIP); + } + if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { + RESTORE_QOS(ddr_data.rga_rd_qos, RGA_RD); + RESTORE_QOS(ddr_data.rga_wr_qos, RGA_WR); + RESTORE_QOS(ddr_data.vop_m0_qos, VOP_M0); + RESTORE_QOS(ddr_data.vop_m1_qos, VOP_M1); + } + if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) { + RESTORE_QOS(ddr_data.vpu_qos, VPU); + RESTORE_QOS(ddr_data.vpu_r128_qos, VPU_R128); + } + if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) { + RESTORE_QOS(ddr_data.emmc_qos, EMMC); + RESTORE_QOS(ddr_data.nand_qos, NAND); + RESTORE_QOS(ddr_data.sdio_qos, SDIO); + RESTORE_QOS(ddr_data.sfc_qos, SFC); + } + if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) + RESTORE_QOS(ddr_data.gmac_qos, GMAC); + if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on) + RESTORE_QOS(ddr_data.crypto_qos, CRYPTO); + if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on) + RESTORE_QOS(ddr_data.sdmmc_qos, SDMMC); + if (pmu_power_domain_st(PD_USB) == pmu_pd_on) { + RESTORE_QOS(ddr_data.usb_host_qos, USB_HOST); + RESTORE_QOS(ddr_data.usb_otg_qos, USB_OTG); + } +} + +static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state) +{ + uint32_t state; + + if (pmu_power_domain_st(pd_id) == pd_state) + goto out; + + if (pd_state == pmu_pd_on) + pmu_power_domain_ctr(pd_id, pd_state); + + state = (pd_state == pmu_pd_off) ? bus_idle : bus_active; + + switch (pd_id) { + case PD_GPU: + pmu_bus_idle_req(BUS_ID_GPU, state); + break; + case PD_VI: + pmu_bus_idle_req(BUS_ID_VI, state); + break; + case PD_VO: + pmu_bus_idle_req(BUS_ID_VO, state); + break; + case PD_VPU: + pmu_bus_idle_req(BUS_ID_VPU, state); + break; + case PD_MMC_NAND: + pmu_bus_idle_req(BUS_ID_MMC, state); + break; + case PD_GMAC: + pmu_bus_idle_req(BUS_ID_GMAC, state); + break; + case PD_CRYPTO: + pmu_bus_idle_req(BUS_ID_CRYPTO, state); + break; + case PD_SDCARD: + pmu_bus_idle_req(BUS_ID_SDCARD, state); + break; + case PD_USB: + pmu_bus_idle_req(BUS_ID_USB, state); + break; + default: + break; + } + + if (pd_state == pmu_pd_off) + pmu_power_domain_ctr(pd_id, pd_state); + +out: + return 0; +} + +static uint32_t pmu_powerdomain_state; + +static void pmu_power_domains_suspend(void) +{ + uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT]; + + clk_gate_con_save(clkgt_save); + clk_gate_con_disable(); + qos_save(); + + pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); + pmu_set_power_domain(PD_GPU, pmu_pd_off); + pmu_set_power_domain(PD_VI, pmu_pd_off); + pmu_set_power_domain(PD_VO, pmu_pd_off); + pmu_set_power_domain(PD_VPU, pmu_pd_off); + pmu_set_power_domain(PD_MMC_NAND, pmu_pd_off); + pmu_set_power_domain(PD_GMAC, pmu_pd_off); + pmu_set_power_domain(PD_CRYPTO, pmu_pd_off); + pmu_set_power_domain(PD_SDCARD, pmu_pd_off); + pmu_set_power_domain(PD_USB, pmu_pd_off); + + clk_gate_con_restore(clkgt_save); +} + +static void pmu_power_domains_resume(void) +{ + uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT]; + + clk_gate_con_save(clkgt_save); + clk_gate_con_disable(); + + if (!(pmu_powerdomain_state & BIT(PD_USB))) + pmu_set_power_domain(PD_USB, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_SDCARD))) + pmu_set_power_domain(PD_SDCARD, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_CRYPTO))) + pmu_set_power_domain(PD_CRYPTO, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_GMAC))) + pmu_set_power_domain(PD_GMAC, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_MMC_NAND))) + pmu_set_power_domain(PD_MMC_NAND, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VPU))) + pmu_set_power_domain(PD_VPU, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VO))) + pmu_set_power_domain(PD_VO, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VI))) + pmu_set_power_domain(PD_VI, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_GPU))) + pmu_set_power_domain(PD_GPU, pmu_pd_on); + + qos_restore(); + clk_gate_con_restore(clkgt_save); +} + +static int check_cpu_wfie(uint32_t cpu) +{ + uint32_t loop = 0, wfie_msk = CKECK_WFEI_MSK << cpu; + + while (!(mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) && + (loop < WFEI_CHECK_LOOP)) { + udelay(1); + loop++; + } + + if ((mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) == 0) { + WARN("%s: %d, %d, error!\n", __func__, cpu, wfie_msk); + return -EINVAL; + } + + return 0; +} + +static int cpus_power_domain_on(uint32_t cpu_id) +{ + uint32_t cpu_pd, apm_value, cfg_info, loop = 0; + + cpu_pd = PD_CPU0 + cpu_id; + cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); + + if (cfg_info == core_pwr_pd) { + /* disable apm cfg */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } + pmu_power_domain_ctr(cpu_pd, pmu_pd_on); + } else { + /* wait cpu down */ + while (pmu_power_domain_st(cpu_pd) == pmu_pd_on && loop < 100) { + udelay(2); + loop++; + } + + /* return error if can't wait cpu down */ + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + WARN("%s:can't wait cpu down\n", __func__); + return -EINVAL; + } + + /* power up cpu in power down state */ + apm_value = BIT(core_pm_sft_wakeup_en); + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(apm_value)); + } + + return 0; +} + +static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) +{ + uint32_t cpu_pd, apm_value; + + cpu_pd = PD_CPU0 + cpu_id; + if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) + return 0; + + if (pd_cfg == core_pwr_pd) { + if (check_cpu_wfie(cpu_id)) + return -EINVAL; + /* disable apm cfg */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } else { + set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); + apm_value = BIT(core_pm_en) | BIT(core_pm_dis_int); + if (pd_cfg == core_pwr_wfi_int) + apm_value |= BIT(core_pm_int_wakeup_en); + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(apm_value)); + } + + return 0; +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, cpu; + + boot_cpu = plat_my_core_pos(); + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { + if (cpu == boot_cpu) + continue; + cpus_power_domain_off(cpu, core_pwr_pd); + } +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, + uint64_t entrypoint) +{ + uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpu_id] = entrypoint; + dsb(); + + cpus_power_domain_on(cpu_id); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_off(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_suspend(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; + cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint(); + dsb(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi_int); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_resume(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + /* Disable core_pm */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + + return PSCI_E_SUCCESS; +} + +#define CLK_MSK_GATING(msk, con) \ + mmio_write_32(CRU_BASE + (con), ((msk) << 16) | 0xffff) +#define CLK_MSK_UNGATING(msk, con) \ + mmio_write_32(CRU_BASE + (con), ((~(msk)) << 16) | 0xffff) + +static uint32_t clk_ungt_msk[CRU_CLKGATES_CON_CNT] = { + 0xe0ff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0380, 0x0000, 0x0000, + 0x07c0, 0x0000, 0x0000, 0x000f, + 0x0061, 0x1f02, 0x0440, 0x1801, + 0x004b, 0x0000 +}; + +static uint32_t clk_pmu_ungt_msk[CRU_PMU_CLKGATE_CON_CNT] = { + 0xf1ff, 0x0310 +}; + +void clk_gate_suspend(void) +{ + int i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) { + ddr_data.cru_clk_gate[i] = + mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + WITH_16BITS_WMSK(~clk_ungt_msk[i])); + } + + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) { + ddr_data.cru_pmu_clk_gate[i] = + mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i)); + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + WITH_16BITS_WMSK(~clk_pmu_ungt_msk[i])); + } +} + +void clk_gate_resume(void) +{ + int i; + + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + WITH_16BITS_WMSK(ddr_data.cru_pmu_clk_gate[i])); + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + WITH_16BITS_WMSK(ddr_data.cru_clk_gate[i])); +} + +static void pvtm_32k_config(void) +{ + uint32_t pvtm_freq_khz, pvtm_div; + + ddr_data.pmu_cru_clksel_con0 = + mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0)); + + ddr_data.pgrf_pvtm_con[0] = + mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON0); + ddr_data.pgrf_pvtm_con[1] = + mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON1); + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(0, 0x3, pgrf_pvtm_st)); + dsb(); + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_en)); + dsb(); + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, PVTM_CALC_CNT); + dsb(); + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_st)); + + /* pmugrf_pvtm_st0 will be clear after PVTM start, + * which will cost about 6 cycles of pvtm at least. + * So we wait 30 cycles of pvtm for security. + */ + while (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) < 30) + ; + + dsb(); + while (!(mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST0) & 0x1)) + ; + + pvtm_freq_khz = + (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) * 24000 + + PVTM_CALC_CNT / 2) / PVTM_CALC_CNT; + pvtm_div = (pvtm_freq_khz + 16) / 32; + + /* pvtm_div = div_factor << 2 + 1, + * so div_factor = (pvtm_div - 1) >> 2. + * But the operation ">> 2" will clear the low bit of pvtm_div, + * so we don't have to do "- 1" for compasation + */ + pvtm_div = pvtm_div >> 2; + if (pvtm_div > 0x3f) + pvtm_div = 0x3f; + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(pvtm_div, 0x3f, pgrf_pvtm_div)); + + /* select pvtm as 32k source */ + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0), + BITS_WITH_WMASK(1, 0x3, 14)); +} + +static void pvtm_32k_config_restore(void) +{ + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0), + ddr_data.pmu_cru_clksel_con0 | BITS_WMSK(0x3, 14)); + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + WITH_16BITS_WMSK(ddr_data.pgrf_pvtm_con[0])); + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, + ddr_data.pgrf_pvtm_con[1]); +} + +static void ddr_sleep_config(void) +{ + /* disable ddr pd, sr */ + ddr_data.ddrc_pwrctrl = mmio_read_32(DDR_UPCTL_BASE + 0x30); + mmio_write_32(DDR_UPCTL_BASE + 0x30, BITS_WITH_WMASK(0x0, 0x3, 0)); + + /* disable ddr auto gt */ + ddr_data.ddrgrf_con1 = mmio_read_32(DDRGRF_BASE + 0x4); + mmio_write_32(DDRGRF_BASE + 0x4, BITS_WITH_WMASK(0x0, 0x1f, 0)); + + /* disable ddr standby */ + ddr_data.ddrstdby_con0 = mmio_read_32(DDR_STDBY_BASE + 0x0); + mmio_write_32(DDR_STDBY_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 0)); + while ((mmio_read_32(DDR_UPCTL_BASE + 0x4) & 0x7) != 1) + ; + + /* ddr pmu ctrl */ + ddr_data.ddrgrf_con0 = mmio_read_32(DDRGRF_BASE + 0x0); + mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 5)); + dsb(); + mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x1, 0x1, 4)); + + /* ddr ret sel */ + ddr_data.pmugrf_soc_con0 = + mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(0)); + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0), + BITS_WITH_WMASK(0x0, 0x1, 12)); +} + +static void ddr_sleep_config_restore(void) +{ + /* restore ddr ret sel */ + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0), + ddr_data.pmugrf_soc_con0 | BITS_WMSK(0x1, 12)); + + /* restore ddr pmu ctrl */ + mmio_write_32(DDRGRF_BASE + 0x0, + ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 4)); + dsb(); + mmio_write_32(DDRGRF_BASE + 0x0, + ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 5)); + + /* restore ddr standby */ + mmio_write_32(DDR_STDBY_BASE + 0x0, + ddr_data.ddrstdby_con0 | BITS_WMSK(0x1, 0)); + + /* restore ddr auto gt */ + mmio_write_32(DDRGRF_BASE + 0x4, + ddr_data.ddrgrf_con1 | BITS_WMSK(0x1f, 0)); + + /* restore ddr pd, sr */ + mmio_write_32(DDR_UPCTL_BASE + 0x30, + ddr_data.ddrc_pwrctrl | BITS_WMSK(0x3, 0)); +} + +static void pmu_sleep_config(void) +{ + uint32_t pwrmd_core_lo, pwrmd_core_hi, pwrmd_com_lo, pwrmd_com_hi; + uint32_t pmu_wkup_cfg2_lo; + uint32_t clk_freq_khz; + + /* save pmic_sleep iomux gpio0_a4 */ + ddr_data.pmic_slp_iomux = mmio_read_32(PMUGRF_BASE + GPIO0A_IOMUX); + + ddr_data.pmu_pwrmd_core_l = + mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_LO); + ddr_data.pmu_pwrmd_core_h = + mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_HI); + ddr_data.pmu_pwrmd_cmm_l = + mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO); + ddr_data.pmu_pwrmd_cmm_h = + mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI); + ddr_data.pmu_wkup_cfg2_l = mmio_read_32(PMU_BASE + PMU_WKUP_CFG2_LO); + + pwrmd_core_lo = BIT(pmu_global_int_dis) | + BIT(pmu_core_src_gt) | + BIT(pmu_cpu0_pd) | + BIT(pmu_clr_core) | + BIT(pmu_scu_pd) | + BIT(pmu_l2_idle) | + BIT(pmu_l2_flush) | + BIT(pmu_clr_bus2main) | + BIT(pmu_clr_peri2msch); + + pwrmd_core_hi = BIT(pmu_dpll_pd_en) | + BIT(pmu_apll_pd_en) | + BIT(pmu_cpll_pd_en) | + BIT(pmu_gpll_pd_en) | + BIT(pmu_npll_pd_en); + + pwrmd_com_lo = BIT(pmu_mode_en) | + BIT(pmu_pll_pd) | + BIT(pmu_pmu_use_if) | + BIT(pmu_alive_use_if) | + BIT(pmu_osc_dis) | + BIT(pmu_sref_enter) | + BIT(pmu_ddrc_gt) | + BIT(pmu_clr_pmu) | + BIT(pmu_clr_peri_pmu); + + pwrmd_com_hi = BIT(pmu_clr_bus) | + BIT(pmu_clr_msch) | + BIT(pmu_wakeup_begin_cfg); + + pmu_wkup_cfg2_lo = BIT(pmu_cluster_wkup_en) | + BIT(pmu_gpio_wkup_en) | + BIT(pmu_timer_wkup_en); + + /* set pmic_sleep iomux gpio0_a4 */ + mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, + BITS_WITH_WMASK(1, 0x3, 8)); + + clk_freq_khz = 32; + + mmio_write_32(PMU_BASE + PMU_OSC_CNT_LO, + WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_OSC_CNT_HI, + WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16)); + + mmio_write_32(PMU_BASE + PMU_STABLE_CNT_LO, + WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_STABLE_CNT_HI, + WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16)); + + mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_LO, + WITH_16BITS_WMSK(clk_freq_khz * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_HI, + WITH_16BITS_WMSK(clk_freq_khz * 2 >> 16)); + + /* Pmu's clk has switched to 24M back When pmu FSM counts + * the follow counters, so we should use 24M to calculate + * these counters. + */ + mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_LO, + WITH_16BITS_WMSK(24000 * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_HI, + WITH_16BITS_WMSK(24000 * 2 >> 16)); + + mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_LO, + WITH_16BITS_WMSK(24000 * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_HI, + WITH_16BITS_WMSK(24000 * 2 >> 16)); + + mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_LO, + WITH_16BITS_WMSK(24000 * 5 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_HI, + WITH_16BITS_WMSK(24000 * 5 >> 16)); + + mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_LO, + WITH_16BITS_WMSK(24000 * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_HI, + WITH_16BITS_WMSK(24000 * 2 >> 16)); + + /* Config pmu power mode and pmu wakeup source */ + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO, + WITH_16BITS_WMSK(pwrmd_core_lo)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI, + WITH_16BITS_WMSK(pwrmd_core_hi)); + + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO, + WITH_16BITS_WMSK(pwrmd_com_lo)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI, + WITH_16BITS_WMSK(pwrmd_com_hi)); + + mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO, + WITH_16BITS_WMSK(pmu_wkup_cfg2_lo)); +} + +static void pmu_sleep_restore(void) +{ + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_l)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_h)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_l)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_h)); + mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO, + WITH_16BITS_WMSK(ddr_data.pmu_wkup_cfg2_l)); + + /* restore pmic_sleep iomux */ + mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, + WITH_16BITS_WMSK(ddr_data.pmic_slp_iomux)); +} + +static void soc_sleep_config(void) +{ + ddr_data.gpio0c_iomux = mmio_read_32(PMUGRF_BASE + GPIO0C_IOMUX); + + pmu_sleep_config(); + + ddr_sleep_config(); + + pvtm_32k_config(); +} + +static void soc_sleep_restore(void) +{ + secure_timer_init(); + + pvtm_32k_config_restore(); + + ddr_sleep_config_restore(); + + pmu_sleep_restore(); + + mmio_write_32(PMUGRF_BASE + GPIO0C_IOMUX, + WITH_16BITS_WMSK(ddr_data.gpio0c_iomux)); +} + +static inline void pm_pll_wait_lock(uint32_t pll_base, uint32_t pll_id) +{ + uint32_t delay = PLL_LOCKED_TIMEOUT; + + while (delay > 0) { + if (mmio_read_32(pll_base + PLL_CON(1)) & + PLL_LOCK_MSK) + break; + delay--; + } + + if (delay == 0) + ERROR("Can't wait pll:%d lock\n", pll_id); +} + +static inline void pll_pwr_ctr(uint32_t pll_base, uint32_t pll_id, uint32_t pd) +{ + mmio_write_32(pll_base + PLL_CON(1), + BITS_WITH_WMASK(1, 1, 15)); + if (pd) + mmio_write_32(pll_base + PLL_CON(1), + BITS_WITH_WMASK(1, 1, 14)); + else + mmio_write_32(pll_base + PLL_CON(1), + BITS_WITH_WMASK(0, 1, 14)); +} + +static inline void pll_set_mode(uint32_t pll_id, uint32_t mode) +{ + uint32_t val = BITS_WITH_WMASK(mode, 0x3, PLL_MODE_SHIFT(pll_id)); + + if (pll_id != GPLL_ID) + mmio_write_32(CRU_BASE + CRU_MODE, val); + else + mmio_write_32(PMUCRU_BASE + CRU_PMU_MODE, + BITS_WITH_WMASK(mode, 0x3, 0)); +} + +static inline void pll_suspend(uint32_t pll_id) +{ + int i; + uint32_t pll_base; + + if (pll_id != GPLL_ID) + pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0); + else + pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0); + + /* save pll con */ + for (i = 0; i < PLL_CON_CNT; i++) + ddr_data.cru_plls_con_save[pll_id][i] = + mmio_read_32(pll_base + PLL_CON(i)); + + /* slow mode */ + pll_set_mode(pll_id, SLOW_MODE); +} + +static inline void pll_resume(uint32_t pll_id) +{ + uint32_t mode, pll_base; + + if (pll_id != GPLL_ID) { + pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0); + mode = (ddr_data.cru_mode_save >> PLL_MODE_SHIFT(pll_id)) & 0x3; + } else { + pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0); + mode = ddr_data.cru_pmu_mode_save & 0x3; + } + + /* if pll locked before suspend, we should wait atfer resume */ + if (ddr_data.cru_plls_con_save[pll_id][1] & PLL_LOCK_MSK) + pm_pll_wait_lock(pll_base, pll_id); + + pll_set_mode(pll_id, mode); +} + +static void pm_plls_suspend(void) +{ + ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_MODE); + ddr_data.cru_pmu_mode_save = mmio_read_32(PMUCRU_BASE + CRU_PMU_MODE); + ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(0)); + + pll_suspend(GPLL_ID); + pll_suspend(NPLL_ID); + pll_suspend(CPLL_ID); + pll_suspend(APLL_ID); + + /* core */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + BITS_WITH_WMASK(0, 0xf, 0)); + + /* pclk_dbg */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + BITS_WITH_WMASK(0, 0xf, 8)); +} + +static void pm_plls_resume(void) +{ + /* pclk_dbg */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + ddr_data.clk_sel0 | BITS_WMSK(0xf, 8)); + + /* core */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + ddr_data.clk_sel0 | BITS_WMSK(0xf, 0)); + + pll_resume(APLL_ID); + pll_resume(CPLL_ID); + pll_resume(NPLL_ID); + pll_resume(GPLL_ID); +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + pmu_power_domains_suspend(); + + clk_gate_suspend(); + + soc_sleep_config(); + + pm_plls_suspend(); + + psram_boot_cfg->pm_flag &= ~PM_WARM_BOOT_BIT; + + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + psram_boot_cfg->pm_flag |= PM_WARM_BOOT_BIT; + + pm_plls_resume(); + + soc_sleep_restore(); + + clk_gate_resume(); + + pmu_power_domains_resume(); + + plat_rockchip_gic_cpuif_enable(); + + return 0; +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + pll_set_mode(GPLL_ID, SLOW_MODE); + pll_set_mode(CPLL_ID, SLOW_MODE); + pll_set_mode(NPLL_ID, SLOW_MODE); + pll_set_mode(APLL_ID, SLOW_MODE); + dsb(); + + mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE); + dsb(); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to execute valid codes. + */ + psci_power_down_wfi(); +} + +void __dead2 rockchip_soc_system_off(void) +{ + uint32_t val; + + /* set pmic_sleep pin(gpio0_a4) to gpio mode */ + mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, BITS_WITH_WMASK(0, 0x3, 8)); + + /* config output */ + val = mmio_read_32(GPIO0_BASE + SWPORTA_DDR); + val |= BIT(4); + mmio_write_32(GPIO0_BASE + SWPORTA_DDR, val); + + /* config output high level */ + val = mmio_read_32(GPIO0_BASE); + val |= BIT(4); + mmio_write_32(GPIO0_BASE, val); + dsb(); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to execute valid codes. + */ + psci_power_down_wfi(); +} + +void rockchip_plat_mmu_el3(void) +{ + /* TODO: support the el3 for px30 SoCs */ +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + rockchip_pd_lock_init(); + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = 0; + + psram_boot_cfg->ddr_func = (uint64_t)0; + psram_boot_cfg->ddr_data = (uint64_t)0; + psram_boot_cfg->sp = PSRAM_SP_TOP; + psram_boot_cfg->ddr_flag = 0x0; + psram_boot_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; + psram_boot_cfg->pm_flag = PM_WARM_BOOT_BIT; + + nonboot_cpus_off(); + + /* Remap pmu_sram's base address to boot address */ + mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0), + BITS_WITH_WMASK(1, 0x1, 13)); + + INFO("%s: pd status %x\n", + __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); +} diff --git a/plat/rockchip/px30/drivers/pmu/pmu.h b/plat/rockchip/px30/drivers/pmu/pmu.h new file mode 100644 index 00000000..416d1c1b --- /dev/null +++ b/plat/rockchip/px30/drivers/pmu/pmu.h @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PMU_H__ +#define __PMU_H__ + +/* Needed aligned 16 bytes for sp stack top */ +#define PSRAM_SP_TOP ((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf) + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WKUP_CFG0_LO 0x00 +#define PMU_WKUP_CFG0_HI 0x04 +#define PMU_WKUP_CFG1_LO 0x08 +#define PMU_WKUP_CFG1_HI 0x0c +#define PMU_WKUP_CFG2_LO 0x10 + +#define PMU_PWRDN_CON 0x18 +#define PMU_PWRDN_ST 0x20 + +#define PMU_PWRMODE_CORE_LO 0x24 +#define PMU_PWRMODE_CORE_HI 0x28 +#define PMU_PWRMODE_COMMON_CON_LO 0x2c +#define PMU_PWRMODE_COMMON_CON_HI 0x30 + +#define PMU_SFT_CON 0x34 +#define PMU_INT_ST 0x44 +#define PMU_BUS_IDLE_REQ 0x64 +#define PMU_BUS_IDLE_ST 0x6c + +#define PMU_OSC_CNT_LO 0x74 +#define PMU_OSC_CNT_HI 0x78 +#define PMU_PLLLOCK_CNT_LO 0x7c +#define PMU_PLLLOCK_CNT_HI 0x80 +#define PMU_PLLRST_CNT_LO 0x84 +#define PMU_PLLRST_CNT_HI 0x88 +#define PMU_STABLE_CNT_LO 0x8c +#define PMU_STABLE_CNT_HI 0x90 +#define PMU_WAKEUP_RST_CLR_LO 0x9c +#define PMU_WAKEUP_RST_CLR_HI 0xa0 + +#define PMU_DDR_SREF_ST 0xa4 + +#define PMU_SYS_REG0_LO 0xa8 +#define PMU_SYS_REG0_HI 0xac +#define PMU_SYS_REG1_LO 0xb0 +#define PMU_SYS_REG1_HI 0xb4 +#define PMU_SYS_REG2_LO 0xb8 +#define PMU_SYS_REG2_HI 0xbc +#define PMU_SYS_REG3_LO 0xc0 +#define PMU_SYS_REG3_HI 0xc4 + +#define PMU_SCU_PWRDN_CNT_LO 0xc8 +#define PMU_SCU_PWRDN_CNT_HI 0xcc +#define PMU_SCU_PWRUP_CNT_LO 0xd0 +#define PMU_SCU_PWRUP_CNT_HI 0xd4 + +#define PMU_TIMEOUT_CNT_LO 0xd8 +#define PMU_TIMEOUT_CNT_HI 0xdc + +#define PMU_CPUAPM_CON(cpu) (0xe0 + (cpu) * 0x4) + +#define CORES_PM_DISABLE 0x0 +#define CLST_CPUS_MSK 0xf + +#define PD_CTR_LOOP 500 +#define PD_CHECK_LOOP 500 +#define WFEI_CHECK_LOOP 500 +#define BUS_IDLE_LOOP 1000 + +enum pmu_wkup_cfg2 { + pmu_cluster_wkup_en = 0, + pmu_gpio_wkup_en = 2, + pmu_sdio_wkup_en = 3, + pmu_sdmmc_wkup_en = 4, + pmu_uart0_wkup_en = 5, + pmu_timer_wkup_en = 6, + pmu_usbdev_wkup_en = 7, + pmu_sft_wkup_en = 8, + pmu_timeout_wkup_en = 10, +}; + +enum pmu_powermode_core_lo { + pmu_global_int_dis = 0, + pmu_core_src_gt = 1, + pmu_cpu0_pd = 3, + pmu_clr_core = 5, + pmu_scu_pd = 6, + pmu_l2_idle = 8, + pmu_l2_flush = 9, + pmu_clr_bus2main = 10, + pmu_clr_peri2msch = 11, +}; + +enum pmu_powermode_core_hi { + pmu_apll_pd_en = 3, + pmu_dpll_pd_en = 4, + pmu_cpll_pd_en = 5, + pmu_gpll_pd_en = 6, + pmu_npll_pd_en = 7, +}; + +enum pmu_powermode_common_lo { + pmu_mode_en = 0, + pmu_ddr_pd_en = 1, + pmu_wkup_rst = 3, + pmu_pll_pd = 4, + pmu_pmu_use_if = 6, + pmu_alive_use_if = 7, + pmu_osc_dis = 8, + pmu_input_clamp = 9, + pmu_sref_enter = 10, + pmu_ddrc_gt = 11, + pmu_ddrio_ret = 12, + pmu_ddrio_ret_deq = 13, + pmu_clr_pmu = 14, + pmu_clr_peri_pmu = 15, +}; + +enum pmu_powermode_common_hi { + pmu_clr_bus = 0, + pmu_clr_mmc = 1, + pmu_clr_msch = 2, + pmu_clr_nandc = 3, + pmu_clr_gmac = 4, + pmu_clr_vo = 5, + pmu_clr_vi = 6, + pmu_clr_gpu = 7, + pmu_clr_usb = 8, + pmu_clr_vpu = 9, + pmu_clr_crypto = 10, + pmu_wakeup_begin_cfg = 11, + pmu_peri_clk_src_gt = 12, + pmu_bus_clk_src_gt = 13, +}; + +enum pmu_pd_id { + PD_CPU0 = 0, + PD_CPU1 = 1, + PD_CPU2 = 2, + PD_CPU3 = 3, + PD_SCU = 4, + PD_USB = 5, + PD_DDR = 6, + PD_SDCARD = 8, + PD_CRYPTO = 9, + PD_GMAC = 10, + PD_MMC_NAND = 11, + PD_VPU = 12, + PD_VO = 13, + PD_VI = 14, + PD_GPU = 15, + PD_END = 16, +}; + +enum pmu_bus_id { + BUS_ID_BUS = 0, + BUS_ID_BUS2MAIN = 1, + BUS_ID_GPU = 2, + BUS_ID_CORE = 3, + BUS_ID_CRYPTO = 4, + BUS_ID_MMC = 5, + BUS_ID_GMAC = 6, + BUS_ID_VO = 7, + BUS_ID_VI = 8, + BUS_ID_SDCARD = 9, + BUS_ID_USB = 10, + BUS_ID_MSCH = 11, + BUS_ID_PERI = 12, + BUS_ID_PMU = 13, + BUS_ID_VPU = 14, + BUS_ID_PERI2MSCH = 15, +}; + +enum pmu_pd_state { + pmu_pd_on = 0, + pmu_pd_off = 1 +}; + +enum pmu_bus_state { + bus_active = 0, + bus_idle = 1, +}; + +enum cores_pm_ctr_mode { + core_pwr_pd = 0, + core_pwr_wfi = 1, + core_pwr_wfi_int = 2 +}; + +enum pmu_cores_pm_by_wfi { + core_pm_en = 0, + core_pm_int_wakeup_en, + core_pm_dis_int, + core_pm_sft_wakeup_en +}; + +/***************************************************************************** + * pmu_sgrf + *****************************************************************************/ +#define PMUSGRF_SOC_CON(i) ((i) * 0x4) + +/***************************************************************************** + * pmu_grf + *****************************************************************************/ +#define GPIO0A_IOMUX 0x0 +#define GPIO0B_IOMUX 0x4 +#define GPIO0C_IOMUX 0x8 +#define GPIO0A_PULL 0x10 + +#define GPIO0L_SMT 0x38 +#define GPIO0H_SMT 0x3c + +#define PMUGRF_SOC_CON(i) (0x100 + (i) * 4) + +#define PMUGRF_PVTM_CON0 0x180 +#define PMUGRF_PVTM_CON1 0x184 +#define PMUGRF_PVTM_ST0 0x190 +#define PMUGRF_PVTM_ST1 0x194 + +#define PVTM_CALC_CNT 0x200 + +#define PMUGRF_OS_REG(n) (0x200 + (n) * 4) + +#define GPIO0A6_IOMUX_MSK (0x3 << 12) +#define GPIO0A6_IOMUX_GPIO (0x0 << 12) +#define GPIO0A6_IOMUX_RSTOUT (0x1 << 12) +#define GPIO0A6_IOMUX_SHTDN (0x2 << 12) + +enum px30_pmugrf_pvtm_con0 { + pgrf_pvtm_st = 0, + pgrf_pvtm_en = 1, + pgrf_pvtm_div = 2, +}; + +/***************************************************************************** + * pmu_cru + *****************************************************************************/ +#define CRU_PMU_MODE 0x20 +#define CRU_PMU_CLKSEL_CON 0x40 +#define CRU_PMU_CLKSELS_CON(i) (CRU_PMU_CLKSEL_CON + (i) * 4) +#define CRU_PMU_CLKSEL_CON_CNT 5 +#define CRU_PMU_CLKGATE_CON 0x80 +#define CRU_PMU_CLKGATES_CON(i) (CRU_PMU_CLKGATE_CON + (i) * 4) +#define CRU_PMU_CLKGATE_CON_CNT 2 +#define CRU_PMU_ATCS_CON 0xc0 +#define CRU_PMU_ATCSS_CON(i) (CRU_PMU_ATCS_CON + (i) * 4) +#define CRU_PMU_ATCS_CON_CNT 2 + +/***************************************************************************** + * pmusgrf + *****************************************************************************/ +#define PMUSGRF_RSTOUT_EN (0x7 << 10) +#define PMUSGRF_RSTOUT_FST 10 +#define PMUSGRF_RSTOUT_TSADC 11 +#define PMUSGRF_RSTOUT_WDT 12 + +#define PMUGRF_SOC_CON2_US_WMSK (0x1fff << 16) +#define PMUGRF_SOC_CON2_MAX_341US 0x1fff +#define PMUGRF_SOC_CON2_200US 0x12c0 + +#define PMUGRF_FAILSAFE_SHTDN_TSADC BIT(0) +#define PMUGRF_FAILSAFE_SHTDN_WDT BIT(1) + +/***************************************************************************** + * QOS + *****************************************************************************/ +#define CPU_AXI_QOS_ID_COREID 0x00 +#define CPU_AXI_QOS_REVISIONID 0x04 +#define CPU_AXI_QOS_PRIORITY 0x08 +#define CPU_AXI_QOS_MODE 0x0c +#define CPU_AXI_QOS_BANDWIDTH 0x10 +#define CPU_AXI_QOS_SATURATION 0x14 +#define CPU_AXI_QOS_EXTCONTROL 0x18 +#define CPU_AXI_QOS_NUM_REGS 0x07 + +#define CPU_AXI_CPU_QOS_BASE 0xff508000 +#define CPU_AXI_GPU_QOS_BASE 0xff520000 +#define CPU_AXI_ISP_128M_QOS_BASE 0xff548000 +#define CPU_AXI_ISP_RD_QOS_BASE 0xff548080 +#define CPU_AXI_ISP_WR_QOS_BASE 0xff548100 +#define CPU_AXI_ISP_M1_QOS_BASE 0xff548180 +#define CPU_AXI_VIP_QOS_BASE 0xff548200 +#define CPU_AXI_RGA_RD_QOS_BASE 0xff550000 +#define CPU_AXI_RGA_WR_QOS_BASE 0xff550080 +#define CPU_AXI_VOP_M0_QOS_BASE 0xff550100 +#define CPU_AXI_VOP_M1_QOS_BASE 0xff550180 +#define CPU_AXI_VPU_QOS_BASE 0xff558000 +#define CPU_AXI_VPU_R128_QOS_BASE 0xff558080 +#define CPU_AXI_DCF_QOS_BASE 0xff500000 +#define CPU_AXI_DMAC_QOS_BASE 0xff500080 +#define CPU_AXI_CRYPTO_QOS_BASE 0xff510000 +#define CPU_AXI_GMAC_QOS_BASE 0xff518000 +#define CPU_AXI_EMMC_QOS_BASE 0xff538000 +#define CPU_AXI_NAND_QOS_BASE 0xff538080 +#define CPU_AXI_SDIO_QOS_BASE 0xff538100 +#define CPU_AXI_SFC_QOS_BASE 0xff538180 +#define CPU_AXI_SDMMC_QOS_BASE 0xff52c000 +#define CPU_AXI_USB_HOST_QOS_BASE 0xff540000 +#define CPU_AXI_USB_OTG_QOS_BASE 0xff540080 + +#define PX30_CPU_AXI_SAVE_QOS(array, base) do { \ + array[0] = mmio_read_32(base + CPU_AXI_QOS_ID_COREID); \ + array[1] = mmio_read_32(base + CPU_AXI_QOS_REVISIONID); \ + array[2] = mmio_read_32(base + CPU_AXI_QOS_PRIORITY); \ + array[3] = mmio_read_32(base + CPU_AXI_QOS_MODE); \ + array[4] = mmio_read_32(base + CPU_AXI_QOS_BANDWIDTH); \ + array[5] = mmio_read_32(base + CPU_AXI_QOS_SATURATION); \ + array[6] = mmio_read_32(base + CPU_AXI_QOS_EXTCONTROL); \ +} while (0) + +#define PX30_CPU_AXI_RESTORE_QOS(array, base) do { \ + mmio_write_32(base + CPU_AXI_QOS_ID_COREID, array[0]); \ + mmio_write_32(base + CPU_AXI_QOS_REVISIONID, array[1]); \ + mmio_write_32(base + CPU_AXI_QOS_PRIORITY, array[2]); \ + mmio_write_32(base + CPU_AXI_QOS_MODE, array[3]); \ + mmio_write_32(base + CPU_AXI_QOS_BANDWIDTH, array[4]); \ + mmio_write_32(base + CPU_AXI_QOS_SATURATION, array[5]); \ + mmio_write_32(base + CPU_AXI_QOS_EXTCONTROL, array[6]); \ +} while (0) + +#define SAVE_QOS(array, NAME) \ + PX30_CPU_AXI_SAVE_QOS(array, CPU_AXI_##NAME##_QOS_BASE) +#define RESTORE_QOS(array, NAME) \ + PX30_CPU_AXI_RESTORE_QOS(array, CPU_AXI_##NAME##_QOS_BASE) + +#endif /* __PMU_H__ */ diff --git a/plat/rockchip/px30/drivers/soc/soc.c b/plat/rockchip/px30/drivers/soc/soc.c new file mode 100644 index 00000000..e00561d8 --- /dev/null +++ b/plat/rockchip/px30/drivers/soc/soc.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/console.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#include <ddr_parameter.h> +#include <platform_def.h> +#include <pmu.h> +#include <px30_def.h> +#include <soc.h> +#include <rockchip_sip_svc.h> + +/* Aggregate of all devices in the first GB */ +#define PX30_DEV_RNG0_BASE 0xff000000 +#define PX30_DEV_RNG0_SIZE 0x00ff0000 + +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(PX30_DEV_RNG0_BASE, PX30_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SHARE_MEM_BASE, SHARE_MEM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PARAM_BASE, DDR_PARAM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +void clk_gate_con_save(uint32_t *clkgt_save) +{ + uint32_t i, j; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + clkgt_save[i] = + mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); + j = i; + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++, j++) + clkgt_save[j] = + mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i)); +} + +void clk_gate_con_restore(uint32_t *clkgt_save) +{ + uint32_t i, j; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + WITH_16BITS_WMSK(clkgt_save[i])); + + j = i; + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++, j++) + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + WITH_16BITS_WMSK(clkgt_save[j])); +} + +void clk_gate_con_disable(void) +{ + uint32_t i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + 0xffff0000); + + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + 0xffff0000); +} + +void secure_timer_init(void) +{ + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG, + TIMER_DIS); + + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOAD_COUNT0, 0xffffffff); + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOAD_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG, + TIMER_EN | TIMER_FMODE); +} + +static void sgrf_init(void) +{ + uint32_t i, val; + struct param_ddr_usage usg; + + /* general secure regions */ + usg = ddr_region_usage_parse(DDR_PARAM_BASE, + PLAT_MAX_DDR_CAPACITY_MB); + for (i = 0; i < usg.s_nr; i++) { + /* enable secure */ + val = mmio_read_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_CON_REG); + val |= BIT(7 - i); + mmio_write_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_CON_REG, val); + /* map top and base */ + mmio_write_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_RGN(7 - i), + RG_MAP_SECURE(usg.s_top[i], usg.s_base[i])); + } + + /* set ddr rgn0_top and rga0_top as 0 */ + mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_FW_DDR_RGN(0), 0x0); + + /* set all slave ip into no-secure, except stimer */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(8), 0x00030000); + + /* set master crypto to no-secure, dcf to secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), 0x000f0003); + + /* set DMAC into no-secure */ + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(0), DMA_IRQ_BOOT_NS); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(1), DMA_PERI_CH_NS_15_0); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(2), DMA_PERI_CH_NS_19_16); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(3), DMA_MANAGER_BOOT_NS); + + /* soft reset dma before use */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), DMA_SOFTRST_REQ); + udelay(5); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), DMA_SOFTRST_RLS); +} + +static void soc_reset_config_all(void) +{ + uint32_t tmp; + + /* tsadc and wdt can trigger a first rst */ + tmp = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON); + tmp |= CRU_GLB_RST_TSADC_FST | CRU_GLB_RST_WDT_FST; + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, tmp); + return; + tmp = mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(3)); + tmp &= ~(PMUGRF_FAILSAFE_SHTDN_TSADC | PMUGRF_FAILSAFE_SHTDN_WDT); + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(3), tmp); + + /* wdt pin rst eable */ + mmio_write_32(GRF_BASE + GRF_SOC_CON(2), + BIT_WITH_WMSK(GRF_SOC_CON2_NSWDT_RST_EN)); +} + +void px30_soc_reset_config(void) +{ + uint32_t tmp; + + /* enable soc ip rst hold time cfg */ + tmp = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON); + tmp |= BIT(CRU_GLB_RST_TSADC_EXT) | BIT(CRU_GLB_RST_WDT_EXT); + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, tmp); + /* soc ip rst hold time, 24m */ + tmp = mmio_read_32(CRU_BASE + CRU_GLB_CNT_TH); + tmp &= ~CRU_GLB_CNT_RST_MSK; + tmp |= (CRU_GLB_CNT_RST_1MS / 2); + mmio_write_32(CRU_BASE + CRU_GLB_CNT_TH, tmp); + + mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0), + BIT_WITH_WMSK(PMUSGRF_RSTOUT_FST) | + BIT_WITH_WMSK(PMUSGRF_RSTOUT_TSADC) | + BIT_WITH_WMSK(PMUSGRF_RSTOUT_WDT)); + + /* rst_out pulse time */ + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(2), + PMUGRF_SOC_CON2_MAX_341US | PMUGRF_SOC_CON2_US_WMSK); + + soc_reset_config_all(); +} + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + sgrf_init(); +} diff --git a/plat/rockchip/px30/drivers/soc/soc.h b/plat/rockchip/px30/drivers/soc/soc.h new file mode 100644 index 00000000..69f2de44 --- /dev/null +++ b/plat/rockchip/px30/drivers/soc/soc.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SOC_H__ +#define __SOC_H__ + +#include <plat_private.h> + +#ifndef BITS_WMSK +#define BITS_WMSK(msk, shift) ((msk) << (shift + REG_MSK_SHIFT)) +#endif + +enum plls_id { + APLL_ID = 0, + DPLL_ID, + CPLL_ID, + NPLL_ID, + GPLL_ID, + END_PLL_ID, +}; + +enum pll_mode { + SLOW_MODE, + NORM_MODE, + DEEP_SLOW_MODE, +}; + +/*************************************************************************** + * SGRF + ***************************************************************************/ +#define SGRF_SOC_CON(i) ((i) * 0x4) +#define SGRF_DMAC_CON(i) (0x30 + (i) * 0x4) + +#define SGRF_MST_S_ALL_NS 0xffffffff +#define SGRF_SLV_S_ALL_NS 0xffff0000 +#define DMA_IRQ_BOOT_NS 0xffffffff +#define DMA_PERI_CH_NS_15_0 0xffffffff +#define DMA_PERI_CH_NS_19_16 0x000f000f +#define DMA_MANAGER_BOOT_NS 0x00010001 +#define DMA_SOFTRST_REQ BITS_WITH_WMASK(1, 0x1, 12) +#define DMA_SOFTRST_RLS BITS_WITH_WMASK(0, 0x1, 12) + +/*************************************************************************** + * GRF + ***************************************************************************/ +#define GRF_SOC_CON(i) (0x0400 + (i) * 4) +#define GRF_PD_VO_CON0 0x0434 +#define GRF_SOC_STATUS0 0x0480 +#define GRF_CPU_STATUS0 0x0520 +#define GRF_CPU_STATUS1 0x0524 +#define GRF_SOC_NOC_CON0 0x0530 +#define GRF_SOC_NOC_CON1 0x0534 + +#define CKECK_WFE_MSK 0x1 +#define CKECK_WFI_MSK 0x10 +#define CKECK_WFEI_MSK 0x11 + +#define GRF_SOC_CON2_NSWDT_RST_EN 12 + +/*************************************************************************** + * DDR FIREWALL + ***************************************************************************/ +#define FIREWALL_DDR_FW_DDR_RGN(i) ((i) * 0x4) +#define FIREWALL_DDR_FW_DDR_MST(i) (0x20 + (i) * 0x4) +#define FIREWALL_DDR_FW_DDR_CON_REG 0x40 +#define FIREWALL_DDR_FW_DDR_RGN_NUM 8 +#define FIREWALL_DDR_FW_DDR_MST_NUM 6 + +#define PLAT_MAX_DDR_CAPACITY_MB 4096 +#define RG_MAP_SECURE(top, base) ((((top) - 1) << 16) | (base)) + +/*************************************************************************** + * cru + ***************************************************************************/ +#define CRU_MODE 0xa0 +#define CRU_MISC 0xa4 +#define CRU_GLB_CNT_TH 0xb0 +#define CRU_GLB_RST_ST 0xb4 +#define CRU_GLB_SRST_FST 0xb8 +#define CRU_GLB_SRST_SND 0xbc +#define CRU_GLB_RST_CON 0xc0 + +#define CRU_CLKSEL_CON 0x100 +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + (i) * 4) +#define CRU_CLKSEL_CON_CNT 60 + +#define CRU_CLKGATE_CON 0x200 +#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + (i) * 4) +#define CRU_CLKGATES_CON_CNT 18 + +#define CRU_SOFTRST_CON 0x300 +#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4)) +#define CRU_SOFTRSTS_CON_CNT 12 + +#define CRU_AUTOCS_CON0(id) (0x400 + (id) * 8) +#define CRU_AUTOCS_CON1(id) (0x404 + (id) * 8) + +#define CRU_CONS_GATEID(i) (16 * (i)) +#define GATE_ID(reg, bit) ((reg) * 16 + (bit)) + +#define CRU_GLB_SRST_FST_VALUE 0xfdb9 +#define CRU_GLB_SRST_SND_VALUE 0xeca8 + +#define CRU_GLB_RST_TSADC_EXT 6 +#define CRU_GLB_RST_WDT_EXT 7 + +#define CRU_GLB_CNT_RST_MSK 0xffff +#define CRU_GLB_CNT_RST_1MS 0x5DC0 + +#define CRU_GLB_RST_TSADC_FST BIT(0) +#define CRU_GLB_RST_WDT_FST BIT(1) + +/*************************************************************************** + * pll + ***************************************************************************/ +#define CRU_PLL_CONS(id, i) ((id) * 0x20 + (i) * 4) +#define PLL_CON(i) ((i) * 4) +#define PLL_CON_CNT 5 +#define PLL_LOCK_MSK BIT(10) +#define PLL_MODE_SHIFT(id) ((id) == CPLL_ID ? \ + 2 : \ + ((id) == DPLL_ID ? 4 : 2 * (id))) +#define PLL_MODE_MSK(id) (0x3 << PLL_MODE_SHIFT(id)) + +#define PLL_LOCKED_TIMEOUT 600000U + +/*************************************************************************** + * GPIO + ***************************************************************************/ +#define SWPORTA_DR 0x00 +#define SWPORTA_DDR 0x04 +#define GPIO_INTEN 0x30 +#define GPIO_INT_STATUS 0x40 +#define GPIO_NUMS 4 + +/************************************************** + * secure timer + **************************************************/ + +/* chanal0~5 */ +#define STIMER_CHN_BASE(n) (STIME_BASE + 0x20 * (n)) + +#define TIMER_LOAD_COUNT0 0x0 +#define TIMER_LOAD_COUNT1 0x4 + +#define TIMER_CUR_VALUE0 0x8 +#define TIMER_CUR_VALUE1 0xc + +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INTSTATUS 0x18 + +#define TIMER_DIS 0x0 +#define TIMER_EN 0x1 + +#define TIMER_FMODE (0x0 << 1) +#define TIMER_RMODE (0x1 << 1) + +#define TIMER_LOAD_COUNT0_MSK (0xffffffff) +#define TIMER_LOAD_COUNT1_MSK (0xffffffff00000000) + +void clk_gate_con_save(uint32_t *clkgt_save); +void clk_gate_con_restore(uint32_t *clkgt_save); +void clk_gate_con_disable(void); + +void secure_timer_init(void); +void secure_timer_disable(void); +void px30_soc_reset_config(void); + +#endif /* __SOC_H__ */ diff --git a/plat/rockchip/px30/include/plat.ld.S b/plat/rockchip/px30/include/plat.ld.S new file mode 100644 index 00000000..44cca0da --- /dev/null +++ b/plat/rockchip/px30/include/plat.ld.S @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019, 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 + */ + .pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + KEEP(*(.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/px30/include/plat_sip_calls.h b/plat/rockchip/px30/include/plat_sip_calls.h new file mode 100644 index 00000000..7b6a6a8f --- /dev/null +++ b/plat/rockchip/px30/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_SIP_CALLS_H__ +#define __PLAT_SIP_CALLS_H__ + +#define RK_PLAT_SIP_NUM_CALLS 0 + +#endif /* __PLAT_SIP_CALLS_H__ */ diff --git a/plat/rockchip/px30/include/platform_def.h b/plat/rockchip/px30/include/platform_def.h new file mode 100644 index 00000000..c101cdc8 --- /dev/null +++ b/plat/rockchip/px30/include/platform_def.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019, 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 <common_def.h> +#include <px30_def.h> + +#define DEBUG_XLAT_TABLE 0 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if DEBUG_XLAT_TABLE +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL1 +#define PLATFORM_STACK_SIZE 0x440 +#elif IMAGE_BL2 +#define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL31 +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL32 +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CLUSTER0_CORE_COUNT 4 +#define PLATFORM_CLUSTER1_CORE_COUNT 0 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) + +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 8 + +/* + * This macro defines the deepest retention state possible. A higher state + * id will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF txet, ro, rw, Size: 512KB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x80000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted RAM + */ +#define BL31_BASE (TZRAM_BASE + 0x10000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define ADDR_SPACE_SIZE (1ull << 32) +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 27 + +/******************************************************************************* + * 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) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE PX30_GICD_BASE +#define PLAT_RK_GICC_BASE PX30_GICC_BASE + +#define PLAT_RK_UART_BASE PX30_UART_BASE +#define PLAT_RK_UART_CLOCK PX30_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE PX30_BAUDRATE + +#define PLAT_RK_PRIMARY_CPU 0x0 + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/rockchip/px30/plat_sip_calls.c b/plat/rockchip/px30/plat_sip_calls.c new file mode 100644 index 00000000..a4b8e55c --- /dev/null +++ b/plat/rockchip/px30/plat_sip_calls.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <common/runtime_svc.h> +#include <lib/mmio.h> + +#include <plat_sip_calls.h> +#include <rockchip_sip_svc.h> + +uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/plat/rockchip/px30/platform.mk b/plat/rockchip/px30/platform.mk new file mode 100644 index 00000000..e947682c --- /dev/null +++ b/plat/rockchip/px30/platform.mk @@ -0,0 +1,63 @@ +# +#Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +#SPDX-License-Identifier: BSD-3-Clause +# + + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 + +PLAT_INCLUDES := -Idrivers/arm/gic/common/ \ + -Idrivers/arm/gic/v2/ \ + -Iinclude/plat/common/ \ + -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/drivers/parameter/ \ + -I${RK_PLAT_COMMON}/pmusram \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/include/ + +RK_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 \ + plat/common/aarch64/crash_console_helpers.S \ + ${RK_PLAT}/common/rockchip_gicv2.c + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + plat/common/plat_psci_common.c + +BL31_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/cpus/aarch64/cortex_a35.S \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c + +ENABLE_PLAT_COMPAT := 0 +MULTI_CONSOLE_API := 1 + +include lib/libfdt/libfdt.mk + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) +$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER)) +$(eval $(call add_define,PLAT_WARMBOOT_ADDR_NOT_ALIGN)) diff --git a/plat/rockchip/px30/px30_def.h b/plat/rockchip/px30/px30_def.h new file mode 100644 index 00000000..021165a4 --- /dev/null +++ b/plat/rockchip/px30/px30_def.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PX30_DEF_H__ +#define __PX30_DEF_H__ + +#define MAJOR_VERSION (1) +#define MINOR_VERSION (0) + +#define SIZE_K(n) ((n) * 1024) + +#define WITH_16BITS_WMSK(bits) (0xffff0000 | (bits)) + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PMU_BASE 0xff000000 +#define PMU_SIZE SIZE_K(64) + +#define PMUGRF_BASE 0xff010000 +#define PMUGRF_SIZE SIZE_K(64) + +#define PMUSRAM_BASE 0xff020000 +#define PMUSRAM_SIZE SIZE_K(64) +#define PMUSRAM_RSIZE SIZE_K(8) + +#define UART0_BASE 0xff030000 +#define UART0_SIZE SIZE_K(64) + +#define GPIO0_BASE 0xff040000 +#define GPIO0_SIZE SIZE_K(64) + +#define PMUSGRF_BASE 0xff050000 +#define PMUSGRF_SIZE SIZE_K(64) + +#define INTSRAM_BASE 0xff0e0000 +#define INTSRAM_SIZE SIZE_K(64) + +#define SGRF_BASE 0xff11c000 +#define SGRF_SIZE SIZE_K(16) + +#define GIC400_BASE 0xff130000 +#define GIC400_SIZE SIZE_K(64) + +#define GRF_BASE 0xff140000 +#define GRF_SIZE SIZE_K(64) + +#define UART1_BASE 0xff158000 +#define UART1_SIZE SIZE_K(64) + +#define UART2_BASE 0xff160000 +#define UART2_SIZE SIZE_K(64) + +#define I2C0_BASE 0xff180000 +#define I2C0_SIZE SIZE_K(64) + +#define PWM0_BASE 0xff200000 +#define PWM0_SIZE SIZE_K(32) + +#define PWM1_BASE 0xff208000 +#define PWM1_SIZE SIZE_K(32) + +#define NTIME_BASE 0xff210000 +#define NTIME_SIZE SIZE_K(64) + +#define STIME_BASE 0xff220000 +#define STIME_SIZE SIZE_K(64) + +#define DCF_BASE 0xff230000 +#define DCF_SIZE SIZE_K(64) + +#define GPIO1_BASE 0xff250000 +#define GPIO1_SIZE SIZE_K(64) + +#define GPIO2_BASE 0xff260000 +#define GPIO2_SIZE SIZE_K(64) + +#define GPIO3_BASE 0xff270000 +#define GPIO3_SIZE SIZE_K(64) + +#define DDR_PHY_BASE 0xff2a0000 +#define DDR_PHY_SIZE SIZE_K(64) + +#define CRU_BASE 0xff2b0000 +#define CRU_SIZE SIZE_K(32) + +#define CRU_BOOST_BASE 0xff2b8000 +#define CRU_BOOST_SIZE SIZE_K(16) + +#define PMUCRU_BASE 0xff2bc000 +#define PMUCRU_SIZE SIZE_K(16) + +#define VOP_BASE 0xff460000 +#define VOP_SIZE SIZE_K(16) + +#define SERVER_MSCH_BASE 0xff530000 +#define SERVER_MSCH_SIZE SIZE_K(64) + +#define FIREWALL_DDR_BASE 0xff534000 +#define FIREWALL_DDR_SIZE SIZE_K(16) + +#define DDR_UPCTL_BASE 0xff600000 +#define DDR_UPCTL_SIZE SIZE_K(64) + +#define DDR_MNTR_BASE 0xff610000 +#define DDR_MNTR_SIZE SIZE_K(64) + +#define DDR_STDBY_BASE 0xff620000 +#define DDR_STDBY_SIZE SIZE_K(64) + +#define DDRGRF_BASE 0xff630000 +#define DDRGRF_SIZE SIZE_K(32) + +/************************************************************************** + * UART related constants + **************************************************************************/ +#define PX30_UART_BASE UART2_BASE +#define PX30_BAUDRATE 1500000 +#define PX30_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 +#define SYS_COUNTER_FREQ_IN_MHZ 24 + +/****************************************************************************** + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define PX30_GICD_BASE (GIC400_BASE + 0x1000) +#define PX30_GICC_BASE (GIC400_BASE + 0x2000) +#define PX30_GICR_BASE 0 /* no GICR in GIC-400 */ + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +#define RK_IRQ_SEC_SGI_0 8 +#define RK_IRQ_SEC_SGI_1 9 +#define RK_IRQ_SEC_SGI_2 10 +#define RK_IRQ_SEC_SGI_3 11 +#define RK_IRQ_SEC_SGI_4 12 +#define RK_IRQ_SEC_SGI_5 13 +#define RK_IRQ_SEC_SGI_6 14 +#define RK_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 0 interrupts. + */ +#define PLAT_RK_GICV2_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/ +#define SHARE_MEM_PAGE_NUM 15 +#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4) + +#define DDR_PARAM_BASE 0x02000000 +#define DDR_PARAM_SIZE SIZE_K(4) + +#endif /* __PLAT_DEF_H__ */ diff --git a/plat/rockchip/rk3288/platform.mk b/plat/rockchip/rk3288/platform.mk index 1811b3af..faf7a152 100644 --- a/plat/rockchip/rk3288/platform.mk +++ b/plat/rockchip/rk3288/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -30,7 +30,9 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ plat/common/plat_gicv2.c \ ${RK_PLAT}/common/rockchip_gicv2.c -PLAT_BL_COMMON_SOURCES := plat/common/aarch32/crash_console_helpers.S \ +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + plat/common/aarch32/crash_console_helpers.S \ plat/common/plat_psci_common.c PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \ diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk index fa207aa5..0da4f2dc 100644 --- a/plat/rockchip/rk3328/platform.mk +++ b/plat/rockchip/rk3328/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -28,7 +28,9 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ plat/common/plat_gicv2.c \ ${RK_PLAT}/common/rockchip_gicv2.c -PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ lib/xlat_tables/xlat_tables_common.c \ plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk index f8878f1d..cb0cb896 100644 --- a/plat/rockchip/rk3368/platform.mk +++ b/plat/rockchip/rk3368/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -26,7 +26,9 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ plat/common/plat_gicv2.c \ ${RK_PLAT}/common/rockchip_gicv2.c -PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/xlat_tables_common.c \ lib/xlat_tables/aarch64/xlat_tables.c \ plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 42589b9b..a6b59736 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -890,7 +890,7 @@ static uint32_t gpio_2_4_clk_gate; static void suspend_apio(void) { - struct apio_info *suspend_apio; + struct bl_aux_rk_apio_info *suspend_apio; int i; suspend_apio = plat_get_rockchip_suspend_apio(); @@ -1010,7 +1010,7 @@ static void suspend_apio(void) static void resume_apio(void) { - struct apio_info *suspend_apio; + struct bl_aux_rk_apio_info *suspend_apio; int i; suspend_apio = plat_get_rockchip_suspend_apio(); @@ -1038,7 +1038,7 @@ static void resume_apio(void) static void suspend_gpio(void) { - struct gpio_info *suspend_gpio; + struct bl_aux_gpio_info *suspend_gpio; uint32_t count; int i; @@ -1053,7 +1053,7 @@ static void suspend_gpio(void) static void resume_gpio(void) { - struct gpio_info *suspend_gpio; + struct bl_aux_gpio_info *suspend_gpio; uint32_t count; int i; @@ -1491,7 +1491,7 @@ int rockchip_soc_sys_pwr_dm_resume(void) void __dead2 rockchip_soc_soft_reset(void) { - struct gpio_info *rst_gpio; + struct bl_aux_gpio_info *rst_gpio; rst_gpio = plat_get_rockchip_gpio_reset(); @@ -1508,7 +1508,7 @@ void __dead2 rockchip_soc_soft_reset(void) void __dead2 rockchip_soc_system_off(void) { - struct gpio_info *poweroff_gpio; + struct bl_aux_gpio_info *poweroff_gpio; poweroff_gpio = plat_get_rockchip_gpio_poweroff(); diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.h b/plat/rockchip/rk3399/drivers/pmu/pmu.h index e1ba4104..74db82ff 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.h +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 1d81d7e9..cfc48e8f 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -32,7 +32,9 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ plat/common/plat_gicv3.c \ ${RK_PLAT}/common/rockchip_gicv3.c -PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/xlat_tables_common.c \ lib/xlat_tables/aarch64/xlat_tables.c \ plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c |