Merge pull request #1796 from grandpaul/rpi3-sdhost-driver
RPi3 SDHost driver
diff --git a/Makefile b/Makefile
index 4e606a2..0169f3f 100644
--- a/Makefile
+++ b/Makefile
@@ -432,16 +432,6 @@
$(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled")
endif
-# SMC Calling Convention checks
-ifneq (${SMCCC_MAJOR_VERSION},1)
- ifneq (${SPD},none)
- $(error "SMC Calling Convention 1.X must be used with SPDs")
- endif
- ifeq (${ARCH},aarch32)
- $(error "Only SMCCC 1.X is supported in AArch32 mode.")
- endif
-endif
-
# For RAS_EXTENSION, require that EAs are handled in EL3 first
ifeq ($(RAS_EXTENSION),1)
ifneq ($(HANDLE_EA_EL3_FIRST),1)
@@ -624,7 +614,6 @@
$(eval $(call assert_numeric,ARM_ARCH_MAJOR))
$(eval $(call assert_numeric,ARM_ARCH_MINOR))
-$(eval $(call assert_numeric,SMCCC_MAJOR_VERSION))
################################################################################
# Add definitions to the cpp preprocessor based on the current build options.
@@ -664,7 +653,6 @@
$(eval $(call add_define,RESET_TO_BL31))
$(eval $(call add_define,SEPARATE_CODE_AND_RODATA))
$(eval $(call add_define,RECLAIM_INIT_CODE))
-$(eval $(call add_define,SMCCC_MAJOR_VERSION))
$(eval $(call add_define,SPD_${SPD}))
$(eval $(call add_define,SPIN_ON_BL1_EXIT))
$(eval $(call add_define,SPM_MM))
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index e7abd50..4f53b8e 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -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
*/
@@ -303,38 +303,6 @@
b enter_lower_el_async_ea
end_vector_entry serror_aarch32
-
- /* ---------------------------------------------------------------------
- * This macro takes an argument in x16 that is the index in the
- * 'rt_svc_descs_indices' array, checks that the value in the array is
- * valid, and loads in x15 the pointer to the handler of that service.
- * ---------------------------------------------------------------------
- */
- .macro load_rt_svc_desc_pointer
- /* Load descriptor index from array of indices */
- adr x14, rt_svc_descs_indices
- ldrb w15, [x14, x16]
-
-#if SMCCC_MAJOR_VERSION == 1
- /* Any index greater than 127 is invalid. Check bit 7. */
- tbnz w15, 7, smc_unknown
-#elif SMCCC_MAJOR_VERSION == 2
- /* Verify that the top 3 bits of the loaded index are 0 (w15 <= 31) */
- cmp w15, #31
- b.hi smc_unknown
-#endif /* SMCCC_MAJOR_VERSION */
-
- /*
- * Get the descriptor using the index
- * x11 = (base + off), w15 = index
- *
- * handler = (base + off) + (index << log2(size))
- */
- adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
- lsl w10, w15, #RT_SVC_SIZE_LOG2
- ldr x15, [x11, w10, uxtw]
- .endm
-
/* ---------------------------------------------------------------------
* The following code handles secure monitor calls.
* Depending upon the execution state from where the SMC has been
@@ -363,56 +331,27 @@
mov x5, xzr
mov x6, sp
-#if SMCCC_MAJOR_VERSION == 1
-
/* Get the unique owning entity number */
ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH
ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH
orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH
- load_rt_svc_desc_pointer
-
-#elif SMCCC_MAJOR_VERSION == 2
-
- /* Bit 31 must be set */
- tbz x0, #FUNCID_TYPE_SHIFT, smc_unknown
-
- /*
- * Check MSB of namespace to decide between compatibility/vendor and
- * SPCI/SPRT
- */
- tbz x0, #(FUNCID_NAMESPACE_SHIFT + 1), compat_or_vendor
-
- /* Namespace is b'10 (SPRT) or b'11 (SPCI) */
-#if ENABLE_SPM
- tst x0, #(1 << FUNCID_NAMESPACE_SHIFT)
- adr x15, spci_smc_handler
- adr x16, sprt_smc_handler
- csel x15, x15, x16, ne
- b prepare_enter_handler
-#else
- b smc_unknown
-#endif
-
-compat_or_vendor:
+ /* Load descriptor index from array of indices */
+ adr x14, rt_svc_descs_indices
+ ldrb w15, [x14, x16]
- /* Namespace is b'00 (compatibility) or b'01 (vendor) */
+ /* Any index greater than 127 is invalid. Check bit 7. */
+ tbnz w15, 7, smc_unknown
/*
- * Add the LSB of the namespace (bit [28]) to the OEN [27:24] to create
- * a 5-bit index into the rt_svc_descs_indices array.
+ * Get the descriptor using the index
+ * x11 = (base + off), w15 = index
*
- * The low 16 entries of the rt_svc_descs_indices array correspond to
- * OENs of the compatibility namespace and the top 16 entries of the
- * array are assigned to the vendor namespace descriptor.
+ * handler = (base + off) + (index << log2(size))
*/
- ubfx x16, x0, #FUNCID_OEN_SHIFT, #(FUNCID_OEN_WIDTH + 1)
-
- load_rt_svc_desc_pointer
-
-prepare_enter_handler:
-
-#endif /* SMCCC_MAJOR_VERSION */
+ adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
+ lsl w10, w15, #RT_SVC_SIZE_LOG2
+ ldr x15, [x11, w10, uxtw]
/*
* Restore the saved C runtime stack value which will become the new
diff --git a/common/bl_common.c b/common/bl_common.c
index b2d22c1..84ff99c 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -58,92 +58,6 @@
return value;
}
-/******************************************************************************
- * Determine whether the memory region delimited by 'addr' and 'size' is free,
- * given the extents of free memory.
- * Return 1 if it is free, 0 if it is not free or if the input values are
- * invalid.
- *****************************************************************************/
-int is_mem_free(uintptr_t free_base, size_t free_size,
- uintptr_t addr, size_t size)
-{
- uintptr_t free_end, requested_end;
-
- /*
- * Handle corner cases first.
- *
- * The order of the 2 tests is important, because if there's no space
- * left (i.e. free_size == 0) but we don't ask for any memory
- * (i.e. size == 0) then we should report that the memory is free.
- */
- if (size == 0)
- return 1; /* A zero-byte region is always free */
- if (free_size == 0)
- return 0;
-
- /*
- * Check that the end addresses don't overflow.
- * If they do, consider that this memory region is not free, as this
- * is an invalid scenario.
- */
- if (check_uptr_overflow(free_base, free_size - 1))
- return 0;
- free_end = free_base + (free_size - 1);
-
- if (check_uptr_overflow(addr, size - 1))
- return 0;
- requested_end = addr + (size - 1);
-
- /*
- * Finally, check that the requested memory region lies within the free
- * region.
- */
- return (addr >= free_base) && (requested_end <= free_end);
-}
-
-/* Generic function to return the size of an image */
-size_t get_image_size(unsigned int image_id)
-{
- uintptr_t dev_handle;
- uintptr_t image_handle;
- uintptr_t image_spec;
- size_t image_size = 0U;
- int io_result;
-
- /* Obtain a reference to the image by querying the platform layer */
- io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
- if (io_result != 0) {
- WARN("Failed to obtain reference to image id=%u (%i)\n",
- image_id, io_result);
- return 0;
- }
-
- /* Attempt to access the image */
- io_result = io_open(dev_handle, image_spec, &image_handle);
- if (io_result != 0) {
- WARN("Failed to access image id=%u (%i)\n",
- image_id, io_result);
- return 0;
- }
-
- /* Find the size of the image */
- io_result = io_size(image_handle, &image_size);
- if ((io_result != 0) || (image_size == 0U)) {
- WARN("Failed to determine the size of the image id=%u (%i)\n",
- image_id, io_result);
- }
- io_result = io_close(image_handle);
- /* Ignore improbable/unrecoverable error in 'close' */
-
- /* TODO: Consider maintaining open device connection from this
- * bootloader stage
- */
- io_result = io_dev_close(dev_handle);
- /* Ignore improbable/unrecoverable error in 'dev_close' */
-
- return image_size;
-}
-
/*******************************************************************************
* Internal function to load an image at a specific address given
* an image ID and extents of free memory.
diff --git a/common/runtime_svc.c b/common/runtime_svc.c
index 09ce787..a2c0c09 100644
--- a/common/runtime_svc.c
+++ b/common/runtime_svc.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
*/
@@ -29,7 +29,6 @@
* Function to invoke the registered `handle` corresponding to the smc_fid in
* AArch32 mode.
******************************************************************************/
-#if SMCCC_MAJOR_VERSION == 1
uintptr_t handle_runtime_svc(uint32_t smc_fid,
void *cookie,
void *handle,
@@ -55,7 +54,6 @@
return rt_svc_descs[index].handle(smc_fid, x1, x2, x3, x4, cookie,
handle, flags);
}
-#endif /* SMCCC_MAJOR_VERSION */
/*******************************************************************************
* Simple routine to sanity check a runtime service descriptor before using it
@@ -71,14 +69,9 @@
if (desc->end_oen >= OEN_LIMIT)
return -EINVAL;
-#if SMCCC_MAJOR_VERSION == 1
if ((desc->call_type != SMC_TYPE_FAST) &&
(desc->call_type != SMC_TYPE_YIELD))
return -EINVAL;
-#elif SMCCC_MAJOR_VERSION == 2
- if (desc->is_vendor > 1U)
- return -EINVAL;
-#endif /* SMCCC_MAJOR_VERSION */
/* A runtime service having no init or handle function doesn't make sense */
if ((desc->init == NULL) && (desc->handle == NULL))
@@ -149,17 +142,10 @@
* descriptor which will handle the SMCs for this owning
* entity range.
*/
-#if SMCCC_MAJOR_VERSION == 1
start_idx = (uint8_t)get_unique_oen(service->start_oen,
service->call_type);
end_idx = (uint8_t)get_unique_oen(service->end_oen,
service->call_type);
-#elif SMCCC_MAJOR_VERSION == 2
- start_idx = (uint8_t)get_rt_desc_idx(service->start_oen,
- service->is_vendor);
- end_idx = (uint8_t)get_rt_desc_idx(service->end_oen,
- service->is_vendor);
-#endif
assert(start_idx <= end_idx);
assert(end_idx < MAX_RT_SVCS);
for (; start_idx <= end_idx; start_idx++)
diff --git a/docs/coding-guidelines.rst b/docs/coding-guidelines.rst
new file mode 100644
index 0000000..d5ac978
--- /dev/null
+++ b/docs/coding-guidelines.rst
@@ -0,0 +1,556 @@
+Trusted Firmware-A Coding Guidelines
+====================================
+
+.. section-numbering::
+ :suffix: .
+
+.. contents::
+
+The following sections contain TF coding guidelines. They are continually
+evolving and should not be considered "set in stone". Feel free to question them
+and provide feedback.
+
+Some of the guidelines may also apply to other codebases.
+
+**Note:** the existing TF codebase does not necessarily comply with all the
+below guidelines but the intent is for it to do so eventually.
+
+Checkpatch overrides
+--------------------
+
+Some checkpatch warnings in the TF codebase are deliberately ignored. These
+include:
+
+- ``**WARNING: line over 80 characters**``: Although the codebase should
+ generally conform to the 80 character limit this is overly restrictive in some
+ cases.
+
+- ``**WARNING: Use of volatile is usually wrong``: see
+ `Why the “volatile” type class should not be used`_ . Although this document
+ contains some very useful information, there are several legimate uses of the
+ volatile keyword within the TF codebase.
+
+Headers and inclusion
+---------------------
+
+Header guards
+^^^^^^^^^^^^^
+
+For a header file called "some_driver.h" the style used by the Trusted Firmware
+is:
+
+.. code:: c
+
+ #ifndef SOME_DRIVER_H
+ #define SOME_DRIVER_H
+
+ <header content>
+
+ #endif /* SOME_DRIVER_H */
+
+Include statement ordering
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+All header files that are included by a source file must use the following,
+grouped ordering. This is to improve readability (by making it easier to quickly
+read through the list of headers) and maintainability.
+
+#. *System* includes: Header files from the standard *C* library, such as
+ ``stddef.h`` and ``string.h``.
+
+#. *Project* includes: Header files under the ``include/`` directory within TF
+ are *project* includes.
+
+#. *Platform* includes: Header files relating to a single, specific platform,
+ and which are located under the ``plat/<platform_name>`` directory within TF,
+ are *platform* includes.
+
+Within each group, ``#include`` statements must be in alphabetical order,
+taking both the file and directory names into account.
+
+Groups must be separated by a single blank line for clarity.
+
+The example below illustrates the ordering rules using some contrived header
+file names; this type of name reuse should be otherwise avoided.
+
+.. code:: c
+
+ #include <string.h>
+
+ #include <a_dir/example/a_header.h>
+ #include <a_dir/example/b_header.h>
+ #include <a_dir/test/a_header.h>
+ #include <b_dir/example/a_header.h>
+
+ #include "./a_header.h"
+
+Include statement variants
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Two variants of the ``#include`` directive are acceptable in the TF codebase.
+Correct use of the two styles improves readability by suggesting the location
+of the included header and reducing ambiguity in cases where generic and
+platform-specific headers share a name.
+
+For header files that are in the same directory as the source file that is
+including them, use the ``"..."`` variant.
+
+For header files that are **not** in the same directory as the source file that
+is including them, use the ``<...>`` variant.
+
+Example (bl1_fwu.c):
+
+.. code:: c
+
+ #include <assert.h>
+ #include <errno.h>
+ #include <string.h>
+
+ #include "bl1_private.h"
+
+Platform include paths
+^^^^^^^^^^^^^^^^^^^^^^
+
+Platforms are allowed to add more include paths to be passed to the compiler.
+The ``PLAT_INCLUDES`` variable is used for this purpose. This is needed in
+particular for the file ``platform_def.h``.
+
+Example:
+
+.. code:: c
+
+ PLAT_INCLUDES += -Iinclude/plat/myplat/include
+
+Types and typedefs
+------------------
+
+Use of built-in *C* and *libc* data types
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The TF codebase should be kept as portable as possible, especially since both
+64-bit and 32-bit platforms are supported. To help with this, the following data
+type usage guidelines should be followed:
+
+- Where possible, use the built-in *C* data types for variable storage (for
+ example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99*
+ types. Most code is typically only concerned with the minimum size of the
+ data stored, which the built-in *C* types guarantee.
+
+- Avoid using the exact-size standard *C99* types in general (for example,
+ ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the
+ compiler from making optimizations. There are legitimate uses for them,
+ for example to represent data of a known structure. When using them in struct
+ definitions, consider how padding in the struct will work across architectures.
+ For example, extra padding may be introduced in AArch32 systems if a struct
+ member crosses a 32-bit boundary.
+
+- Use ``int`` as the default integer type - it's likely to be the fastest on all
+ systems. Also this can be assumed to be 32-bit as a consequence of the
+ `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call
+ Standard for the Arm 64-bit Architecture`_ .
+
+- Avoid use of ``short`` as this may end up being slower than ``int`` in some
+ systems. If a variable must be exactly 16-bit, use ``int16_t`` or
+ ``uint16_t``.
+
+- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given
+ that `int` is 32-bit on Arm platforms, there is no use for it. For integers of
+ at least 64-bit, use ``long long``.
+
+- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data.
+
+- Use ``unsigned`` for integers that can never be negative (counts,
+ indices, sizes, etc). TF intends to comply with MISRA "essential type" coding
+ rules (10.X), where signed and unsigned types are considered different
+ essential types. Choosing the correct type will aid this. MISRA static
+ analysers will pick up any implicit signed/unsigned conversions that may lead
+ to unexpected behaviour.
+
+- For pointer types:
+
+ - If an argument in a function declaration is pointing to a known type then
+ simply use a pointer to that type (for example: ``struct my_struct *``).
+
+ - If a variable (including an argument in a function declaration) is pointing
+ to a general, memory-mapped address, an array of pointers or another
+ structure that is likely to require pointer arithmetic then use
+ ``uintptr_t``. This will reduce the amount of casting required in the code.
+ Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it
+ may work but is less portable.
+
+ - For other pointer arguments in a function declaration, use ``void *``. This
+ includes pointers to types that are abstracted away from the known API and
+ pointers to arbitrary data. This allows the calling function to pass a
+ pointer argument to the function without any explicit casting (the cast to
+ ``void *`` is implicit). The function implementation can then do the
+ appropriate casting to a specific type.
+
+ - Use ``ptrdiff_t`` to compare the difference between 2 pointers.
+
+- Use ``size_t`` when storing the ``sizeof()`` something.
+
+- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that
+ can also return an error code; the signed type allows for a negative return
+ code in case of error. This practice should be used sparingly.
+
+- Use ``u_register_t`` when it's important to store the contents of a register
+ in its native size (32-bit in AArch32 and 64-bit in AArch64). This is not a
+ standard *C99* type but is widely available in libc implementations,
+ including the FreeBSD version included with the TF codebase. Where possible,
+ cast the variable to a more appropriate type before interpreting the data. For
+ example, the following struct in ``ep_info.h`` could use this type to minimize
+ the storage required for the set of registers:
+
+.. code:: c
+
+ 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;
+
+
+ If some code wants to operate on ``arg0`` and knows that it represents a
+ 32-bit unsigned integer on all systems, cast it to ``unsigned int``.
+
+These guidelines should be updated if additional types are needed.
+
+Avoid anonymous typedefs of structs/enums in headers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For example, the following definition:
+
+.. code:: c
+
+ typedef struct {
+ int arg1;
+ int arg2;
+ } my_struct_t;
+
+
+is better written as:
+
+.. code:: c
+
+ struct my_struct {
+ int arg1;
+ int arg2;
+ };
+
+This allows function declarations in other header files that depend on the
+struct/enum to forward declare the struct/enum instead of including the
+entire header:
+
+.. code:: c
+
+ #include <my_struct.h>
+ void my_func(my_struct_t *arg);
+
+instead of:
+
+.. code:: c
+
+ struct my_struct;
+ void my_func(struct my_struct *arg);
+
+Some TF definitions use both a struct/enum name **and** a typedef name. This
+is discouraged for new definitions as it makes it difficult for TF to comply
+with MISRA rule 8.3, which states that "All declarations of an object or
+function shall use the same names and type qualifiers".
+
+The Linux coding standards also discourage new typedefs and checkpatch emits
+a warning for this.
+
+Existing typedefs will be retained for compatibility.
+
+Error handling and robustness
+-----------------------------
+
+Using CASSERT to check for compile time data errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Where possible, use the ``CASSERT`` macro to check the validity of data known at
+compile time instead of checking validity at runtime, to avoid unnecessary
+runtime code.
+
+For example, this can be used to check that the assembler's and compiler's views
+of the size of an array is the same.
+
+.. code:: c
+
+ #include <cassert.h>
+
+ define MY_STRUCT_SIZE 8 /* Used by assembler source files */
+
+ struct my_struct {
+ uint32_t arg1;
+ uint32_t arg2;
+ };
+
+ CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch);
+
+
+If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would
+emit an error like this:
+
+.. code:: c
+
+ my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative
+
+
+Using assert() to check for programming errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be
+treated as a tightly integrated package; the image builder should be aware of
+and responsible for all functionality within the image, even if code within that
+image is provided by multiple entities. This allows us to be more aggressive in
+interpreting invalid state or bad function arguments as programming errors using
+``assert()``, including arguments passed across platform porting interfaces.
+This is in contrast to code in a Linux environment, which is less tightly
+integrated and may attempt to be more defensive by passing the error back up the
+call stack.
+
+Where possible, badly written TF code should fail early using ``assert()``. This
+helps reduce the amount of untested conditional code. By default these
+statements are not compiled into release builds, although this can be overridden
+using the ``ENABLE_ASSERTIONS`` build flag.
+
+Examples:
+
+- Bad argument supplied to library function
+- Bad argument provided by platform porting function
+- Internal secure world image state is inconsistent
+
+
+Handling integration errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Each secure world image may be provided by a different entity (for example, a
+Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32
+image and the OEM/SoC vendor may provide the other images).
+
+An image may contain bugs that are only visible when the images are integrated.
+The system integrator may not even have access to the debug variants of all the
+images in order to check if asserts are firing. For example, the release variant
+of BL1 may have already been burnt into the SoC. Therefore, TF code that detects
+an integration error should _not_ consider this a programming error, and should
+always take action, even in release builds.
+
+If an integration error is considered non-critical it should be treated as a
+recoverable error. If the error is considered critical it should be treated as
+an unexpected unrecoverable error.
+
+Handling recoverable errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The secure world **must not** crash when supplied with bad data from an external
+source. For example, data from the normal world or a hardware device. Similarly,
+the secure world **must not** crash if it detects a non-critical problem within
+itself or the system. It must make every effort to recover from the problem by
+emitting a ``WARN`` message, performing any necessary error handling and
+continuing.
+
+Examples:
+
+- Secure world receives SMC from normal world with bad arguments.
+- Secure world receives SMC from normal world at an unexpected time.
+- BL31 receives SMC from BL32 with bad arguments.
+- BL31 receives SMC from BL32 at unexpected time.
+- Secure world receives recoverable error from hardware device. Retrying the
+ operation may help here.
+- Non-critical secure world service is not functioning correctly.
+- BL31 SPD discovers minor configuration problem with corresponding SP.
+
+Handling unrecoverable errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In some cases it may not be possible for the secure world to recover from an
+error. This situation should be handled in one of the following ways:
+
+1. If the unrecoverable error is unexpected then emit an ``ERROR`` message and
+ call ``panic()``. This will end up calling the platform-specific function
+ ``plat_panic_handler()``.
+2. If the unrecoverable error is expected to occur in certain circumstances,
+ then emit an ``ERROR`` message and call the platform-specific function
+ ``plat_error_handler()``.
+
+Cases 1 and 2 are subtly different. A platform may implement ``plat_panic_handler``
+and ``plat_error_handler`` in the same way (for example, by waiting for a secure
+watchdog to time-out or by invoking an interface on the platform's power
+controller to reset the platform). However, ``plat_error_handler`` may take
+additional action for some errors (for example, it may set a flag so the
+platform resets into a different mode). Also, ``plat_panic_handler()`` may
+implement additional debug functionality (for example, invoking a hardware
+breakpoint).
+
+Examples of unexpected unrecoverable errors:
+
+- BL32 receives an unexpected SMC response from BL31 that it is unable to
+ recover from.
+- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding
+ Trusted OS, which is critical for platform operation.
+- Secure world discovers that a critical hardware device is an unexpected and
+ unrecoverable state.
+- Secure world receives an unexpected and unrecoverable error from a critical
+ hardware device.
+- Secure world discovers that it is running on unsupported hardware.
+
+Examples of expected unrecoverable errors:
+
+- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk.
+- BL1/BL2 fails to authenticate the next image due to an invalid certificate.
+- Secure world continuously receives recoverable errors from a hardware device
+ but is unable to proceed without a valid response.
+
+Handling critical unresponsiveness
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If the secure world is waiting for a response from an external source (for
+example, the normal world or a hardware device) which is critical for continued
+operation, it must not wait indefinitely. It must have a mechanism (for example,
+a secure watchdog) for resetting itself and/or the external source to prevent
+the system from executing in this state indefinitely.
+
+Examples:
+
+- BL1 is waiting for the normal world to raise an SMC to proceed to the next
+ stage of the secure firmware update process.
+- A Trusted OS is waiting for a response from a proxy in the normal world that
+ is critical for continued operation.
+- Secure world is waiting for a hardware response that is critical for continued
+ operation.
+
+Security considerations
+-----------------------
+
+Part of the security of a platform is handling errors correctly, as described in
+the previous section. There are several other security considerations covered in
+this section.
+
+Do not leak secrets to the normal world
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The secure world **must not** leak secrets to the normal world, for example in
+response to an SMC.
+
+Handling Denial of Service attacks
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The secure world **should never** crash or become unusable due to receiving too
+many normal world requests (a *Denial of Service* or *DoS* attack). It should
+have a mechanism for throttling or ignoring normal world requests.
+
+Performance considerations
+--------------------------
+
+Avoid printf and use logging macros
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``)
+which wrap ``tf_log`` and which allow the logging call to be compiled-out
+depending on the ``make`` command. Use these macros to avoid print statements
+being compiled unconditionally into the binary.
+
+Each logging macro has a numerical log level:
+
+.. code:: c
+
+ #define LOG_LEVEL_NONE 0
+ #define LOG_LEVEL_ERROR 10
+ #define LOG_LEVEL_NOTICE 20
+ #define LOG_LEVEL_WARNING 30
+ #define LOG_LEVEL_INFO 40
+ #define LOG_LEVEL_VERBOSE 50
+
+
+By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will
+be compiled into debug builds and all statements with a log level
+``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be
+overridden from the command line or by the platform makefile (although it may be
+necessary to clean the build directory first). For example, to enable
+``VERBOSE`` logging on FVP:
+
+``make PLAT=fvp LOG_LEVEL=50 all``
+
+Use const data where possible
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For example, the following code:
+
+.. code:: c
+
+ struct my_struct {
+ int arg1;
+ int arg2;
+ };
+
+ void init(struct my_struct *ptr);
+
+ void main(void)
+ {
+ struct my_struct x;
+ x.arg1 = 1;
+ x.arg2 = 2;
+ init(&x);
+ }
+
+is better written as:
+
+.. code:: c
+
+ struct my_struct {
+ int arg1;
+ int arg2;
+ };
+
+ void init(const struct my_struct *ptr);
+
+ void main(void)
+ {
+ const struct my_struct x = { 1, 2 };
+ init(&x);
+ }
+
+This allows the linker to put the data in a read-only data section instead of a
+writeable data section, which may result in a smaller and faster binary. Note
+that this may require dependent functions (``init()`` in the above example) to
+have ``const`` arguments, assuming they don't need to modify the data.
+
+Library and driver code
+-----------------------
+
+TF library code (under ``lib/`` and ``include/lib``) is any code that provides a
+reusable interface to other code, potentially even to code outside of TF.
+
+In some systems drivers must conform to a specific driver framework to provide
+services to the rest of the system. TF has no driver framework and the
+distinction between a driver and library is somewhat subjective.
+
+A driver (under ``drivers/`` and ``include/drivers/``) is defined as code that
+interfaces with hardware via a memory mapped interface.
+
+Some drivers (for example, the Arm CCI driver in ``include/drivers/arm/cci.h``)
+provide a general purpose API to that specific hardware. Other drivers (for
+example, the Arm PL011 console driver in ``drivers/arm/pl011/pl011_console.S``)
+provide a specific hardware implementation of a more abstract library API. In
+the latter case there may potentially be multiple drivers for the same hardware
+device.
+
+Neither libraries nor drivers should depend on platform-specific code. If they
+require platform-specific data (for example, a base address) to operate then
+they should provide an initialization function that takes the platform-specific
+data as arguments.
+
+TF common code (under ``common/`` and ``include/common/``) is code that is re-used
+by other generic (non-platform-specific) TF code. It is effectively internal
+library code.
+
+.. _`Why the “volatile” type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html
+.. _`Procedure Call Standard for the Arm Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf
+.. _`Procedure Call Standard for the Arm 64-bit Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 7fc5297..716d446 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -1198,9 +1198,6 @@
meminfo.total_base = Base address of secure RAM visible to BL1
meminfo.total_size = Size of secure RAM visible to BL1
- meminfo.free_base = Base address of secure RAM available for allocation
- to BL1
- meminfo.free_size = Size of secure RAM available for allocation to BL1
This information is used by BL1 to load the BL2 image in secure RAM. BL1 also
populates a similar structure to tell BL2 the extents of memory available for
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index b50de37..320bb1d 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -86,6 +86,46 @@
git clone https://github.com/ARM-software/arm-trusted-firmware.git
+Checking source code style
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Trusted Firmware follows the `Linux Coding Style`_ . When making changes to the
+source, for submission to the project, the source must be in compliance with
+this style guide.
+
+Additional, project-specific guidelines are defined in the `Trusted Firmware-A
+Coding Guidelines`_ document.
+
+To assist with coding style compliance, the project Makefile contains two
+targets which both utilise the `checkpatch.pl` script that ships with the Linux
+source tree. The project also defines certain *checkpatch* options in the
+``.checkpatch.conf`` file in the top-level directory.
+
+**Note:** Checkpatch errors will gate upstream merging of pull requests.
+Checkpatch warnings will not gate merging but should be reviewed and fixed if
+possible.
+
+To check the entire source tree, you must first download copies of
+``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available
+in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH``
+environment variable to point to ``checkpatch.pl`` (with the other 2 files in
+the same directory) and build the `checkcodebase` target:
+
+::
+
+ make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkcodebase
+
+To just check the style on the files that differ between your local branch and
+the remote master, use:
+
+::
+
+ make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkpatch
+
+If you wish to check your patch against something other than the remote master,
+set the ``BASE_COMMIT`` variable to your desired branch. By default, ``BASE_COMMIT``
+is set to ``origin/master``.
+
Building TF-A
-------------
@@ -234,12 +274,6 @@
compiling TF-A. Its value must be a numeric, and defaults to 0. See also,
*Armv8 Architecture Extensions* in `Firmware Design`_.
-- ``ARM_PLAT_MT``: This flag determines whether the Arm platform layer has to
- cater for the multi-threading ``MT`` bit when accessing MPIDR. When this flag
- is set, the functions which deal with MPIDR assume that the ``MT`` bit in
- MPIDR is set and access the bit-fields in MPIDR accordingly. Default value of
- this flag is 0. Note that this option is not used on FVP platforms.
-
- ``BL2``: This is an optional build option which specifies the path to BL2
image for the ``fip`` target. In this case, the BL2 in the TF-A will not be
built.
@@ -628,11 +662,6 @@
pages" section in `Firmware Design`_. This flag is disabled by default and
affects all BL images.
-- ``SMCCC_MAJOR_VERSION``: Numeric value that indicates the major version of
- the SMC Calling Convention that the Trusted Firmware supports. The only two
- allowed values are 1 and 2, and it defaults to 1. The minor version is
- determined using this value.
-
- ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A.
This build option is only valid if ``ARCH=aarch64``. The value should be
the path to the directory containing the SPD source, relative to
@@ -735,6 +764,12 @@
Linux Image address must be specified using the ``PRELOADED_BL33_BASE``
option.
+- ``ARM_PLAT_MT``: This flag determines whether the Arm platform layer has to
+ cater for the multi-threading ``MT`` bit when accessing MPIDR. When this flag
+ is set, the functions which deal with MPIDR assume that the ``MT`` bit in
+ MPIDR is set and access the bit-fields in MPIDR accordingly. Default value of
+ this flag is 0. Note that this option is not used on FVP platforms.
+
- ``ARM_RECOM_STATE_ID_ENC``: The PSCI1.0 specification recommends an encoding
for the construction of composite state-ID in the power-state parameter.
The existing PSCI clients currently do not support this encoding of
@@ -930,34 +965,6 @@
build/<platform>/<build-type>/bl32.bin
-Checking source code style
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When making changes to the source for submission to the project, the source
-must be in compliance with the Linux style guide, and to assist with this check
-the project Makefile contains two targets, which both utilise the
-``checkpatch.pl`` script that ships with the Linux source tree.
-
-To check the entire source tree, you must first download copies of
-``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available
-in the `Linux master tree`_ scripts directory, then set the ``CHECKPATCH``
-environment variable to point to ``checkpatch.pl`` (with the other 2 files in
-the same directory) and build the target checkcodebase:
-
-::
-
- make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkcodebase
-
-To just check the style on the files that differ between your local branch and
-the remote master, use:
-
-::
-
- make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkpatch
-
-If you wish to check your patch against something other than the remote master,
-set the ``BASE_COMMIT`` variable to your desired branch. By default, ``BASE_COMMIT``
-is set to ``origin/master``.
Building and using the FIP tool
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2045,7 +2052,7 @@
--------------
-*Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.*
.. _Linaro: `Linaro Release Notes`_
.. _Linaro Release: `Linaro Release Notes`_
@@ -2054,6 +2061,7 @@
.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/w/docs/303/juno
.. _Arm Platforms Portal: https://community.arm.com/dev-platforms/
.. _Development Studio 5 (DS-5): http://www.arm.com/products/tools/software-tools/ds-5/index.php
+.. _`Linux Coding Style`: https://www.kernel.org/doc/html/latest/process/coding-style.html
.. _Linux master tree: https://github.com/torvalds/linux/tree/master/
.. _Dia: https://wiki.gnome.org/Apps/Dia/Download
.. _here: psci-lib-integration-guide.rst
@@ -2069,3 +2077,4 @@
.. _Juno Getting Started Guide: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf
.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
.. _Secure Partition Manager Design guide: secure-partition-manager-design.rst
+.. _`Trusted Firmware-A Coding Guidelines`: coding-guidelines.rst
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 450bd0b..77d683c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -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
*/
@@ -300,7 +300,7 @@
break;
}
- if (ret != 0) {
+ if (ret < 0) {
return ret;
}
diff --git a/drivers/renesas/rcar/cpld/ulcb_cpld.c b/drivers/renesas/rcar/cpld/ulcb_cpld.c
index 6b03614..4830853 100644
--- a/drivers/renesas/rcar/cpld/ulcb_cpld.c
+++ b/drivers/renesas/rcar/cpld/ulcb_cpld.c
@@ -24,6 +24,9 @@
#define GPIO_INOUTSEL2 0xE6052004
#define GPIO_INOUTSEL6 0xE6055404
+/* General IO/Interrupt Switching Register */
+#define GPIO_IOINTSEL6 0xE6055400
+
/* GPIO/perihperal function select */
#define PFC_GPSR2 0xE6060108
#define PFC_GPSR6 0xE6060118
@@ -93,6 +96,7 @@
gpio_pfc(PFC_GPSR2, SSTBZ);
gpio_pfc(PFC_GPSR6, MOSI);
+ gpio_set_value(GPIO_IOINTSEL6, SCLK, 0);
gpio_set_value(GPIO_OUTDT6, SCLK, 0);
gpio_set_value(GPIO_OUTDT2, SSTBZ, 1);
gpio_set_value(GPIO_OUTDT6, MOSI, 0);
diff --git a/drivers/renesas/rcar/pwrc/pwrc.c b/drivers/renesas/rcar/pwrc/pwrc.c
index b005caf..d7f0880 100644
--- a/drivers/renesas/rcar/pwrc/pwrc.c
+++ b/drivers/renesas/rcar/pwrc/pwrc.c
@@ -768,3 +768,43 @@
done:
return count;
}
+
+int32_t rcar_pwrc_cpu_on_check(uint64_t mpidr)
+{
+ uint64_t i;
+ uint64_t j;
+ uint64_t cpu_count;
+ uintptr_t reg_PSTR;
+ uint32_t status;
+ uint64_t my_cpu;
+ int32_t rtn;
+ uint32_t my_cluster_type;
+
+ const uint32_t cluster_type[PLATFORM_CLUSTER_COUNT] = {
+ RCAR_CLUSTER_CA53,
+ RCAR_CLUSTER_CA57
+ };
+ const uintptr_t registerPSTR[PLATFORM_CLUSTER_COUNT] = {
+ RCAR_CA53PSTR,
+ RCAR_CA57PSTR
+ };
+
+ my_cluster_type = rcar_pwrc_get_cluster();
+
+ rtn = 0;
+ my_cpu = mpidr & ((uint64_t)(MPIDR_CPU_MASK));
+ for (i = 0U; i < ((uint64_t)(PLATFORM_CLUSTER_COUNT)); i++) {
+ cpu_count = rcar_pwrc_get_cpu_num(cluster_type[i]);
+ reg_PSTR = registerPSTR[i];
+ for (j = 0U; j < cpu_count; j++) {
+ if ((my_cluster_type != cluster_type[i]) || (my_cpu != j)) {
+ status = mmio_read_32(reg_PSTR) >> (j * 4U);
+ if ((status & 0x00000003U) == 0U) {
+ rtn--;
+ }
+ }
+ }
+ }
+ return (rtn);
+
+}
diff --git a/drivers/renesas/rcar/pwrc/pwrc.h b/drivers/renesas/rcar/pwrc/pwrc.h
index 3cdac69..d4d6fc4 100644
--- a/drivers/renesas/rcar/pwrc/pwrc.h
+++ b/drivers/renesas/rcar/pwrc/pwrc.h
@@ -44,6 +44,7 @@
void rcar_pwrc_clusteroff(uint64_t mpidr);
void rcar_pwrc_cpuoff(uint64_t mpidr);
void rcar_pwrc_cpuon(uint64_t mpidr);
+int32_t rcar_pwrc_cpu_on_check(uint64_t mpidr);
void rcar_pwrc_setup(void);
uint32_t rcar_pwrc_get_cpu_wkr(uint64_t mpidr);
diff --git a/drivers/staging/renesas/rcar/ddr/ddr_a/ddr_init_e3.c b/drivers/staging/renesas/rcar/ddr/ddr_a/ddr_init_e3.c
index 62997bc..c289c88 100644
--- a/drivers/staging/renesas/rcar/ddr/ddr_a/ddr_init_e3.c
+++ b/drivers/staging/renesas/rcar/ddr/ddr_a/ddr_init_e3.c
@@ -1137,13 +1137,13 @@
/* ddr backupmode end */
if (ddrBackup) {
- NOTICE("[WARM_BOOT]");
+ NOTICE("BL2: [WARM_BOOT]\n");
} else {
- NOTICE("[COLD_BOOT]");
+ NOTICE("BL2: [COLD_BOOT]\n");
} /* ddrBackup */
err = rcar_dram_update_boot_status(ddrBackup);
if (err) {
- NOTICE("[BOOT_STATUS_UPDATE_ERROR]");
+ NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n");
return INITDRAM_ERR_I;
} /* err */
@@ -1672,9 +1672,9 @@
md = *((volatile uint32_t*)RST_MODEMR);
ddr = (md & 0x00080000) >> 19;
if (ddr == 0x0) {
- NOTICE("BL2: DDR1584(%s)", RCAR_E3_DDR_VERSION);
+ NOTICE("BL2: DDR1584(%s)\n", RCAR_E3_DDR_VERSION);
} else if(ddr == 0x1){
- NOTICE("BL2: DDR1856(%s)", RCAR_E3_DDR_VERSION);
+ NOTICE("BL2: DDR1856(%s)\n", RCAR_E3_DDR_VERSION);
} /* ddr */
rcar_dram_get_boot_status(&ddrBackup);
@@ -1691,8 +1691,6 @@
failcount = 1;
} /* dataL */
- NOTICE("..%d\n", failcount); /* rev.0.05 */
-
if (failcount == 0) {
return INITDRAM_OK;
} else {
diff --git a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c
index 78f0f11..f4bfdde 100644
--- a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c
+++ b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c
@@ -2826,7 +2826,7 @@
set_freqchgack(0);
if (timeout) {
- FATAL_MSG("Time out[2]");
+ FATAL_MSG("BL2: Time out[2]\n");
return (1);
}
return (0);
@@ -3012,13 +3012,13 @@
***********************************************************************/
#ifdef DDR_BACKUPMODE
if (ddrBackup) {
- NOTICE("[WARM_BOOT]");
+ NOTICE("BL2: [WARM_BOOT]\n");
} else {
- NOTICE("[COLD_BOOT]");
+ NOTICE("BL2: [COLD_BOOT]\n");
}
err = rcar_dram_update_boot_status(ddrBackup);
if (err) {
- NOTICE("[BOOT_STATUS_UPDATE_ERROR]");
+ NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n");
return INITDRAM_ERR_I;
}
#endif
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 9e2bffa..76c3e27 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -204,6 +204,10 @@
/* ID_AA64MMFR2_EL1 definitions */
#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2
+
+#define ID_AA64MMFR2_EL1_ST_SHIFT U(28)
+#define ID_AA64MMFR2_EL1_ST_MASK ULL(0xf)
+
#define ID_AA64MMFR2_EL1_CNP_SHIFT U(0)
#define ID_AA64MMFR2_EL1_CNP_MASK ULL(0xf)
@@ -427,6 +431,7 @@
#define TCR_TxSZ_MIN ULL(16)
#define TCR_TxSZ_MAX ULL(39)
+#define TCR_TxSZ_MAX_TTST ULL(48)
/* (internal) physical address size bits in EL3/EL1 */
#define TCR_PS_BITS_4GB ULL(0x0)
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 2b09ba0..9bf43bf 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -17,4 +17,10 @@
ID_AA64MMFR2_EL1_CNP_MASK) != 0U;
}
+static inline bool is_armv8_4_ttst_present(void)
+{
+ return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) &
+ ID_AA64MMFR2_EL1_ST_MASK) == 1U;
+}
+
#endif /* ARCH_FEATURES_H */
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index f7b3b9c..57c1174 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -189,11 +189,6 @@
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
-size_t get_image_size(unsigned int image_id);
-
-int is_mem_free(uintptr_t free_base, size_t free_size,
- uintptr_t addr, size_t size);
-
int load_auth_image(unsigned int image_id, image_info_t *image_data);
#if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH)
diff --git a/include/common/runtime_svc.h b/include/common/runtime_svc.h
index 59bf158..e5e36c7 100644
--- a/include/common/runtime_svc.h
+++ b/include/common/runtime_svc.h
@@ -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
*/
@@ -36,17 +36,8 @@
* In SMCCC 1.X, the function identifier has 6 bits for the owning entity number
* and a single bit for the type of smc call. When taken together, those values
* limit the maximum number of runtime services to 128.
- *
- * In SMCCC 2.X the type bit is always 1 and there are only 4 OEN bits in the
- * compatibility namespace, so the total number of services is 16. The LSB of
- * namespace is also added to these 4 bits to make space for the vendor service
- * handler and so the total number of runtime services is 32.
*/
-#if SMCCC_MAJOR_VERSION == 1
#define MAX_RT_SVCS U(128)
-#elif SMCCC_MAJOR_VERSION == 2
-#define MAX_RT_SVCS U(32)
-#endif
#ifndef __ASSEMBLY__
@@ -70,11 +61,7 @@
typedef struct rt_svc_desc {
uint8_t start_oen;
uint8_t end_oen;
-#if SMCCC_MAJOR_VERSION == 1
uint8_t call_type;
-#elif SMCCC_MAJOR_VERSION == 2
- uint8_t is_vendor;
-#endif
const char *name;
rt_svc_init_t init;
rt_svc_handle_t handle;
@@ -83,8 +70,6 @@
/*
* Convenience macros to declare a service descriptor
*/
-#if SMCCC_MAJOR_VERSION == 1
-
#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
static const rt_svc_desc_t __svc_desc_ ## _name \
__section("rt_svc_descs") __used = { \
@@ -96,37 +81,6 @@
.handle = (_smch) \
}
-#elif SMCCC_MAJOR_VERSION == 2
-
-#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
- static const rt_svc_desc_t __svc_desc_ ## _name \
- __section("rt_svc_descs") __used = { \
- .start_oen = (_start), \
- .end_oen = (_end), \
- .is_vendor = 0, \
- .name = #_name, \
- .init = (_setup), \
- .handle = (_smch), \
- }; \
- CASSERT((_type) == SMC_TYPE_FAST, rt_svc_type_check_ ## _name)
-
-/*
- * The higher 16 entries of the runtime services are used for the vendor
- * specific descriptor.
- */
-#define DECLARE_RT_SVC_VENDOR(_setup, _smch) \
- static const rt_svc_desc_t __svc_desc_vendor \
- __section("rt_svc_descs") __used = { \
- .start_oen = 0, \
- .end_oen = 15, \
- .is_vendor = 1, \
- .name = "vendor_rt_svc", \
- .init = _setup, \
- .handle = _smch, \
- }
-
-#endif /* SMCCC_MAJOR_VERSION */
-
/*
* Compile time assertions related to the 'rt_svc_desc' structure to:
* 1. ensure that the assembler and the compiler view of the size
@@ -144,7 +98,6 @@
assert_rt_svc_desc_handle_offset_mismatch);
-#if SMCCC_MAJOR_VERSION == 1
/*
* This function combines the call type and the owning entity number
* corresponding to a runtime service to generate a unique owning entity number.
@@ -169,22 +122,6 @@
return get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid));
}
-#elif SMCCC_MAJOR_VERSION == 2
-
-/*
- * This function combines the owning entity number corresponding to a runtime
- * service with one extra bit for the vendor namespace to generate an index into
- * the 'rt_svc_descs_indices' array. The entry contains the index of the service
- * descriptor in the 'rt_svc_descs' array.
- */
-static inline uint32_t get_rt_desc_idx(uint32_t oen, uint32_t is_vendor)
-{
- return ((is_vendor & 1U) << FUNCID_OEN_WIDTH) |
- (oen & FUNCID_OEN_MASK);
-}
-
-#endif
-
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index b10c52c..94c39d2 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.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
*/
@@ -19,15 +19,69 @@
| (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << \
SMCCC_VERSION_MINOR_SHIFT))
-#if SMCCC_MAJOR_VERSION == 1
-# define SMCCC_MINOR_VERSION U(1)
-# include <lib/smccc_v1.h>
-#elif SMCCC_MAJOR_VERSION == 2
-# define SMCCC_MINOR_VERSION U(0)
-# include <lib/smccc_v2.h>
-#else
-# error "Unsupported version of SMCCC."
-#endif
+#define SMCCC_MAJOR_VERSION U(1)
+#define SMCCC_MINOR_VERSION U(1)
+
+/*******************************************************************************
+ * Bit definitions inside the function id as per the SMC calling convention
+ ******************************************************************************/
+#define FUNCID_TYPE_SHIFT U(31)
+#define FUNCID_TYPE_MASK U(0x1)
+#define FUNCID_TYPE_WIDTH U(1)
+
+#define FUNCID_CC_SHIFT U(30)
+#define FUNCID_CC_MASK U(0x1)
+#define FUNCID_CC_WIDTH U(1)
+
+#define FUNCID_OEN_SHIFT U(24)
+#define FUNCID_OEN_MASK U(0x3f)
+#define FUNCID_OEN_WIDTH U(6)
+
+#define FUNCID_NUM_SHIFT U(0)
+#define FUNCID_NUM_MASK U(0xffff)
+#define FUNCID_NUM_WIDTH U(16)
+
+#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \
+ FUNCID_TYPE_MASK)
+#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \
+ FUNCID_CC_MASK)
+#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \
+ FUNCID_OEN_MASK)
+
+/*******************************************************************************
+ * Owning entity number definitions inside the function id as per the SMC
+ * calling convention
+ ******************************************************************************/
+#define OEN_ARM_START U(0)
+#define OEN_ARM_END U(0)
+#define OEN_CPU_START U(1)
+#define OEN_CPU_END U(1)
+#define OEN_SIP_START U(2)
+#define OEN_SIP_END U(2)
+#define OEN_OEM_START U(3)
+#define OEN_OEM_END U(3)
+#define OEN_STD_START U(4) /* Standard Service Calls */
+#define OEN_STD_END U(4)
+#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */
+#define OEN_STD_HYP_END U(5)
+#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */
+#define OEN_VEN_HYP_END U(6)
+#define OEN_TAP_START U(48) /* Trusted Applications */
+#define OEN_TAP_END U(49)
+#define OEN_TOS_START U(50) /* Trusted OS */
+#define OEN_TOS_END U(63)
+#define OEN_LIMIT U(64)
+
+/* Flags and error codes */
+#define SMC_64 U(1)
+#define SMC_32 U(0)
+
+#define SMC_TYPE_FAST ULL(1)
+#define SMC_TYPE_YIELD ULL(0)
+
+#define SMC_OK ULL(0)
+#define SMC_UNK -1
+#define SMC_PREEMPTED -2 /* Not defined by the SMCCC */
/* Various flags passed to SMC handlers */
#define SMC_FROM_SECURE (U(0) << 0)
diff --git a/include/lib/smccc_v1.h b/include/lib/smccc_v1.h
deleted file mode 100644
index 2b8bd8b..0000000
--- a/include/lib/smccc_v1.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef SMCCC_V1_H
-#define SMCCC_V1_H
-
-#ifndef SMCCC_H
-#error "This file must only be included from smccc.h"
-#endif
-
-/*******************************************************************************
- * Bit definitions inside the function id as per the SMC calling convention
- ******************************************************************************/
-#define FUNCID_TYPE_SHIFT U(31)
-#define FUNCID_TYPE_MASK U(0x1)
-#define FUNCID_TYPE_WIDTH U(1)
-
-#define FUNCID_CC_SHIFT U(30)
-#define FUNCID_CC_MASK U(0x1)
-#define FUNCID_CC_WIDTH U(1)
-
-#define FUNCID_OEN_SHIFT U(24)
-#define FUNCID_OEN_MASK U(0x3f)
-#define FUNCID_OEN_WIDTH U(6)
-
-#define FUNCID_NUM_SHIFT U(0)
-#define FUNCID_NUM_MASK U(0xffff)
-#define FUNCID_NUM_WIDTH U(16)
-
-#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \
- FUNCID_TYPE_MASK)
-#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \
- FUNCID_CC_MASK)
-#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \
- FUNCID_OEN_MASK)
-
-/*******************************************************************************
- * Owning entity number definitions inside the function id as per the SMC
- * calling convention
- ******************************************************************************/
-#define OEN_ARM_START U(0)
-#define OEN_ARM_END U(0)
-#define OEN_CPU_START U(1)
-#define OEN_CPU_END U(1)
-#define OEN_SIP_START U(2)
-#define OEN_SIP_END U(2)
-#define OEN_OEM_START U(3)
-#define OEN_OEM_END U(3)
-#define OEN_STD_START U(4) /* Standard Service Calls */
-#define OEN_STD_END U(4)
-#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */
-#define OEN_STD_HYP_END U(5)
-#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */
-#define OEN_VEN_HYP_END U(6)
-#define OEN_TAP_START U(48) /* Trusted Applications */
-#define OEN_TAP_END U(49)
-#define OEN_TOS_START U(50) /* Trusted OS */
-#define OEN_TOS_END U(63)
-#define OEN_LIMIT U(64)
-
-/* Flags and error codes */
-#define SMC_64 U(1)
-#define SMC_32 U(0)
-
-#define SMC_TYPE_FAST ULL(1)
-#define SMC_TYPE_YIELD ULL(0)
-
-#define SMC_OK ULL(0)
-#define SMC_UNK -1
-#define SMC_PREEMPTED -2 /* Not defined by the SMCCC */
-
-#endif /* SMCCC_V1_H */
diff --git a/include/lib/smccc_v2.h b/include/lib/smccc_v2.h
deleted file mode 100644
index 22bf458..0000000
--- a/include/lib/smccc_v2.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef SMCCC_V2_H
-#define SMCCC_V2_H
-
-#ifndef SMCCC_H
-#error "This file must only be included from smccc.h"
-#endif
-
-/*******************************************************************************
- * Bit definitions inside the function id as per the SMC calling convention
- ******************************************************************************/
-#define FUNCID_TYPE_SHIFT U(31)
-#define FUNCID_TYPE_MASK U(0x1)
-#define FUNCID_TYPE_WIDTH U(1)
-
-#define FUNCID_CC_SHIFT U(30)
-#define FUNCID_CC_MASK U(0x1)
-#define FUNCID_CC_WIDTH U(1)
-
-#define FUNCID_NAMESPACE_SHIFT U(28)
-#define FUNCID_NAMESPACE_MASK U(0x3)
-#define FUNCID_NAMESPACE_WIDTH U(2)
-
-#define FUNCID_OEN_SHIFT U(24)
-#define FUNCID_OEN_MASK U(0xf)
-#define FUNCID_OEN_WIDTH U(4)
-
-#define FUNCID_NUM_SHIFT U(0)
-#define FUNCID_NUM_MASK U(0xffff)
-#define FUNCID_NUM_WIDTH U(16)
-
-#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \
- FUNCID_TYPE_MASK)
-#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \
- FUNCID_CC_MASK)
-#define GET_SMC_NAMESPACE(id) (((id) >> FUNCID_NAMESPACE_SHIFT) & \
- FUNCID_NAMESPACE_MASK)
-#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \
- FUNCID_OEN_MASK)
-
-/*******************************************************************************
- * Owning entity number definitions inside the function id as per the SMC
- * calling convention
- ******************************************************************************/
-#define OEN_ARM_START U(0)
-#define OEN_ARM_END U(0)
-#define OEN_CPU_START U(1)
-#define OEN_CPU_END U(1)
-#define OEN_SIP_START U(2)
-#define OEN_SIP_END U(2)
-#define OEN_OEM_START U(3)
-#define OEN_OEM_END U(3)
-#define OEN_STD_START U(4) /* Standard Service Calls */
-#define OEN_STD_END U(4)
-#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */
-#define OEN_STD_HYP_END U(5)
-#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */
-#define OEN_VEN_HYP_END U(6)
-#define OEN_LIMIT U(16)
-
-/*******************************************************************************
- * Service namespaces as per the SMC Calling Convention v2.X
- ******************************************************************************/
-#define FUNCID_NAMESPACE_START U(0)
-#define FUNCID_NAMESPACE_COMPAT U(0)
-#define FUNCID_NAMESPACE_VENDOR U(1)
-#define FUNCID_NAMESPACE_SPRT U(2)
-#define FUNCID_NAMESPACE_SPCI U(3)
-#define FUNCID_NAMESPACE_LIMIT U(4)
-
-/* Flags and error codes */
-#define SMC_64 U(1)
-#define SMC_32 U(0)
-
-#define SMC_TYPE_FAST ULL(1)
-
-#define SMC_OK ULL(0)
-#define SMC_UNK -1
-
-#endif /* SMCCC_V2_H */
diff --git a/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
index a333d1e..30eb5e9 100644
--- a/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
+++ b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
@@ -63,8 +63,7 @@
* is 1.
*
* Note that this macro assumes that the given virtual address space size is
- * valid. Therefore, the caller is expected to check it is the case using the
- * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ * valid.
*/
#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \
(((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) ? \
diff --git a/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
index cc5624c..3014c8f 100644
--- a/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
+++ b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
@@ -43,14 +43,22 @@
* state.
*
* TCR.TxSZ is calculated as 64 minus the width of said address space.
- * The value of TCR.TxSZ must be in the range 16 to 39 [1], which means that
- * the virtual address space width must be in the range 48 to 25 bits.
+ * The value of TCR.TxSZ must be in the range 16 to 39 [1] or 48 [2],
+ * depending on Small Translation Table Support which means that
+ * the virtual address space width must be in the range 48 to 25 or 16 bits.
*
* [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
* information:
* Page 1730: 'Input address size', 'For all translation stages'.
+ * [2] See section 12.2.55 in the ARMv8-A Architecture Reference Manual
+ * (DDI 0487D.a)
*/
+/* Maximum value of TCR_ELx.T(0,1)SZ is 39 */
#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MAX))
+
+/* Maximum value of TCR_ELx.T(0,1)SZ is 48 */
+#define MIN_VIRT_ADDR_SPACE_SIZE_TTST \
+ (ULL(1) << (U(64) - TCR_TxSZ_MAX_TTST))
#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MIN))
/*
@@ -58,9 +66,13 @@
* virtual address space size. For a 4 KB page size,
* - level 0 supports virtual address spaces of widths 48 to 40 bits;
* - level 1 from 39 to 31;
- * - level 2 from 30 to 25.
+ * - level 2 from 30 to 22.
+ * - level 3 from 21 to 16.
*
- * Wider or narrower address spaces are not supported. As a result, level 3
+ * Small Translation Table (Armv8.4-TTST) support allows the starting level
+ * of the translation table from 3 for 4KB granularity. See section 12.2.55 in
+ * the ARMv8-A Architecture Reference Manual (DDI 0487D.a). In Armv8.3 and below
+ * wider or narrower address spaces are not supported. As a result, level 3
* cannot be used as initial lookup level with 4 KB granularity. See section
* D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
* information.
@@ -71,13 +83,14 @@
* is 1.
*
* Note that this macro assumes that the given virtual address space size is
- * valid. Therefore, the caller is expected to check it is the case using the
- * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ * valid.
*/
#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \
(((_virt_addr_space_sz) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT)) \
? 0U \
- : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) \
- ? 1U : 2U))
+ : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) \
+ ? 1U \
+ : (((_virt_addr_space_sz) > (ULL(1) << L2_XLAT_ADDRESS_SHIFT)) \
+ ? 2U : 3U)))
#endif /* XLAT_TABLES_AARCH64_H */
diff --git a/include/lib/xlat_tables/xlat_tables_arch.h b/include/lib/xlat_tables/xlat_tables_arch.h
index 251b020..7237534 100644
--- a/include/lib/xlat_tables/xlat_tables_arch.h
+++ b/include/lib/xlat_tables/xlat_tables_arch.h
@@ -14,18 +14,6 @@
#endif
/*
- * Evaluates to 1 if the given virtual address space size is valid, or 0 if it's
- * not.
- *
- * A valid size is one that is a power of 2 and is within the architectural
- * limits. Not that these limits are different for AArch32 and AArch64.
- */
-#define CHECK_VIRT_ADDR_SPACE_SIZE(size) \
- (((unsigned long long)(size) >= MIN_VIRT_ADDR_SPACE_SIZE) && \
- ((unsigned long long)(size) <= MAX_VIRT_ADDR_SPACE_SIZE) && \
- IS_POWER_OF_TWO(size))
-
-/*
* Evaluates to 1 if the given physical address space size is a power of 2,
* or 0 if it's not.
*/
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index ce5cf82..6a1be32 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -125,9 +125,6 @@
#define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \
_xlat_tables_count, _virt_addr_space_size, \
_phy_addr_space_size, _xlat_regime, _section_name)\
- CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size), \
- assert_invalid_virtual_addr_space_size_for_##_ctx_name);\
- \
CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size), \
assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
\
diff --git a/include/services/spci_svc.h b/include/services/spci_svc.h
index b82cf1e..1d02bfa 100644
--- a/include/services/spci_svc.h
+++ b/include/services/spci_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -34,7 +34,10 @@
#define SPCI_FID_TUN_SHIFT U(24)
#define SPCI_FID_TUN_MASK U(0x7)
-#define SPCI_SMC(spci_fid) ((FUNCID_NAMESPACE_SPCI << FUNCID_NAMESPACE_SHIFT) | \
+#define OEN_SPCI_START U(0x30)
+#define OEN_SPCI_END U(0x3F)
+
+#define SPCI_SMC(spci_fid) ((OEN_SPCI_START << FUNCID_OEN_SHIFT) | \
(U(1) << 31) | (spci_fid))
#define SPCI_MISC_32(misc_fid) ((SMC_32 << FUNCID_CC_SHIFT) | \
SPCI_FID_MISC_FLAG | \
diff --git a/include/services/sprt_svc.h b/include/services/sprt_svc.h
index bd695e5..2421ea2 100644
--- a/include/services/sprt_svc.h
+++ b/include/services/sprt_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -37,10 +37,13 @@
/* Definitions to build the complete SMC ID */
-#define SPRT_SMC_64(sprt_fid) ((FUNCID_NAMESPACE_SPRT << FUNCID_NAMESPACE_SHIFT) | \
+#define OEN_SPRT_START U(0x20)
+#define OEN_SPRT_END U(0x2F)
+
+#define SPRT_SMC_64(sprt_fid) ((OEN_SPRT_START << FUNCID_OEN_SHIFT) | \
(U(1) << 31) | ((sprt_fid) & SPRT_FID_MASK) | \
(SMC_64 << FUNCID_CC_SHIFT))
-#define SPRT_SMC_32(sprt_fid) ((FUNCID_NAMESPACE_SPRT << FUNCID_NAMESPACE_SHIFT) | \
+#define SPRT_SMC_32(sprt_fid) ((OEN_SPRT_START << FUNCID_OEN_SHIFT) | \
(U(1) << 31) | ((sprt_fid) & SPRT_FID_MASK) | \
(SMC_32 << FUNCID_CC_SHIFT))
diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c
index 468a9e7..4b01b9b 100644
--- a/lib/xlat_tables/aarch32/xlat_tables.c
+++ b/lib/xlat_tables/aarch32/xlat_tables.c
@@ -55,6 +55,11 @@
{
unsigned long long max_pa;
uintptr_t max_va;
+
+ assert(PLAT_VIRT_ADDR_SPACE_SIZE >= MIN_VIRT_ADDR_SPACE_SIZE);
+ assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE);
+ assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE));
+
print_mmap();
init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE,
&max_va, &max_pa);
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index 71f491a..e64fd3e 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -10,7 +10,7 @@
#include <platform_def.h>
#include <arch.h>
-#include <arch_helpers.h>
+#include <arch_features.h>
#include <common/bl_common.h>
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables.h>
@@ -79,6 +79,21 @@
return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL;
}
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+static uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+ uintptr_t ret;
+
+ if (is_armv8_4_ttst_present())
+ ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
+ else
+ ret = MIN_VIRT_ADDR_SPACE_SIZE;
+
+ return ret;
+}
#endif /* ENABLE_ASSERTIONS */
unsigned int xlat_arch_current_el(void)
@@ -104,6 +119,12 @@
{
unsigned long long max_pa;
uintptr_t max_va;
+
+ assert(PLAT_VIRT_ADDR_SPACE_SIZE >=
+ (xlat_get_min_virt_addr_space_size() - 1U));
+ assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE);
+ assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE));
+
print_mmap();
init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE,
&max_va, &max_pa);
diff --git a/lib/xlat_tables/xlat_tables_private.h b/lib/xlat_tables/xlat_tables_private.h
index 4390f34..82bc70c 100644
--- a/lib/xlat_tables/xlat_tables_private.h
+++ b/lib/xlat_tables/xlat_tables_private.h
@@ -16,9 +16,6 @@
#error xlat tables v2 must be used with HW_ASSISTED_COHERENCY
#endif
-CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(PLAT_VIRT_ADDR_SPACE_SIZE),
- assert_valid_virt_addr_space_size);
-
CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(PLAT_PHY_ADDR_SPACE_SIZE),
assert_valid_phy_addr_space_size);
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index 913c86d..b69c670 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -45,6 +45,14 @@
/* Physical address space size for long descriptor format. */
return (1ULL << 40) - 1ULL;
}
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+ return MIN_VIRT_ADDR_SPACE_SIZE;
+}
#endif /* ENABLE_ASSERTIONS*/
bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
@@ -193,7 +201,12 @@
if (max_va != UINT32_MAX) {
uintptr_t virtual_addr_space_size = max_va + 1U;
- assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+ assert(virtual_addr_space_size >=
+ xlat_get_min_virt_addr_space_size());
+ assert(virtual_addr_space_size <=
+ MAX_VIRT_ADDR_SPACE_SIZE);
+ assert(IS_POWER_OF_TWO(virtual_addr_space_size));
+
/*
* __builtin_ctzll(0) is undefined but here we are guaranteed
* that virtual_addr_space_size is in the range [1, UINT32_MAX].
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index 228f751..e7593dd 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -101,6 +101,21 @@
return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL;
}
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+ uintptr_t ret;
+
+ if (is_armv8_4_ttst_present())
+ ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
+ else
+ ret = MIN_VIRT_ADDR_SPACE_SIZE;
+
+ return ret;
+}
#endif /* ENABLE_ASSERTIONS*/
bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
@@ -221,7 +236,11 @@
assert(max_va < ((uint64_t)UINTPTR_MAX));
virtual_addr_space_size = (uintptr_t)max_va + 1U;
- assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+
+ assert(virtual_addr_space_size >=
+ xlat_get_min_virt_addr_space_size());
+ assert(virtual_addr_space_size <= MAX_VIRT_ADDR_SPACE_SIZE);
+ assert(IS_POWER_OF_TWO(virtual_addr_space_size));
/*
* __builtin_ctzll(0) is undefined but here we are guaranteed that
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index c49554f..4820b4f 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -1146,6 +1146,11 @@
mmap_region_t *mm = ctx->mmap;
+ assert(ctx->va_max_address >=
+ (xlat_get_min_virt_addr_space_size() - 1U));
+ assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U));
+ assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U));
+
xlat_mmap_print(mm);
/* All tables must be zeroed before mapping any region. */
diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index fc70955..70ef395 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -102,4 +102,9 @@
/* Returns true if the data cache is enabled at the current EL. */
bool is_dcache_enabled(void);
+/*
+ * Returns minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void);
+
#endif /* XLAT_TABLES_PRIVATE_H */
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 8ef1bb9..c1aa320 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -153,9 +153,6 @@
# cores stack
RECLAIM_INIT_CODE := 0
-# Default to SMCCC Version 1.X
-SMCCC_MAJOR_VERSION := 1
-
# SPD choice
SPD := none
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index 67b06f4..c3fcc38 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -154,7 +154,8 @@
non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC;
mmio_write_32(EDMAC_SEC_CTRL, non_secure);
- for (i = 0; i < EDMAC_CHANNEL_NUMS; i++) {
+ /* Channel 0 is reserved for LPM3, keep secure */
+ for (i = 1; i < EDMAC_CHANNEL_NUMS; i++) {
mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18));
}
}
diff --git a/plat/imx/common/imx8_psci.c b/plat/imx/common/imx8_psci.c
index 588d8b4..91d3370 100644
--- a/plat/imx/common/imx8_psci.c
+++ b/plat/imx/common/imx8_psci.c
@@ -32,8 +32,22 @@
int imx_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
- /* TODO */
- return PSCI_E_INVALID_PARAMS;
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int pwr_type = psci_get_pstate_type(power_state);
+ int state_id = psci_get_pstate_id(power_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ if (pwr_type == PSTATE_TYPE_POWERDOWN) {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+ if (!state_id)
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_RET_STATE;
+ else
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_OFF_STATE;
+ }
+
+ return PSCI_E_SUCCESS;
}
void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
diff --git a/plat/imx/common/include/plat_imx8.h b/plat/imx/common/include/plat_imx8.h
index 952ad53..be99b97 100644
--- a/plat/imx/common/include/plat_imx8.h
+++ b/plat/imx/common/include/plat_imx8.h
@@ -10,6 +10,11 @@
#include <drivers/arm/gicv3.h>
#include <lib/psci/psci.h>
+struct plat_gic_ctx {
+ gicv3_redist_ctx_t rdist_ctx[PLATFORM_CORE_COUNT];
+ gicv3_dist_ctx_t dist_ctx;
+};
+
unsigned int plat_calc_core_pos(uint64_t mpidr);
void imx_mailbox_init(uintptr_t base_addr);
void plat_gic_driver_init(void);
@@ -24,5 +29,7 @@
psci_power_state_t *req_state);
void imx_get_sys_suspend_power_state(psci_power_state_t *req_state);
bool imx_is_wakeup_src_irqsteer(void);
+void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx);
+void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx);
#endif /* PLAT_IMX8_H */
diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c
index aec0b6c..27c525b 100644
--- a/plat/imx/common/plat_imx8_gic.c
+++ b/plat/imx/common/plat_imx8_gic.c
@@ -73,3 +73,19 @@
{
gicv3_rdistif_init(plat_my_core_pos());
}
+
+void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx)
+{
+ /* save the gic rdist/dist context */
+ for (int i = 0; i < PLATFORM_CORE_COUNT; i++)
+ gicv3_rdistif_save(i, &ctx->rdist_ctx[i]);
+ gicv3_distif_save(&ctx->dist_ctx);
+}
+
+void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx)
+{
+ /* restore the gic rdist/dist context */
+ gicv3_distif_init_restore(&ctx->dist_ctx);
+ for (int i = 0; i < PLATFORM_CORE_COUNT; i++)
+ gicv3_rdistif_init_restore(i, &ctx->rdist_ctx[i]);
+}
diff --git a/plat/imx/common/sci/imx8_mu.c b/plat/imx/common/sci/imx8_mu.c
index 26d9bdf..66e956d 100644
--- a/plat/imx/common/sci/imx8_mu.c
+++ b/plat/imx/common/sci/imx8_mu.c
@@ -8,6 +8,21 @@
#include "imx8_mu.h"
+void MU_Resume(uint32_t base)
+{
+ uint32_t reg, i;
+
+ reg = mmio_read_32(base + MU_ACR_OFFSET1);
+ /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+ reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1
+ | MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1);
+ mmio_write_32(base + MU_ACR_OFFSET1, reg);
+
+ /* Enable all RX interrupts */
+ for (i = 0; i < MU_RR_COUNT; i++)
+ MU_EnableRxFullInt(base, i);
+}
+
void MU_EnableRxFullInt(uint32_t base, uint32_t index)
{
uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1);
diff --git a/plat/imx/common/sci/imx8_mu.h b/plat/imx/common/sci/imx8_mu.h
index 8c78877..edcac7b 100644
--- a/plat/imx/common/sci/imx8_mu.h
+++ b/plat/imx/common/sci/imx8_mu.h
@@ -33,3 +33,4 @@
void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg);
void MU_EnableGeneralInt(uint32_t base, uint32_t index);
void MU_EnableRxFullInt(uint32_t base, uint32_t index);
+void MU_Resume(uint32_t base);
diff --git a/plat/imx/imx8qm/imx8qm_bl31_setup.c b/plat/imx/imx8qm/imx8qm_bl31_setup.c
index a00695c..c76de64 100644
--- a/plat/imx/imx8qm/imx8qm_bl31_setup.c
+++ b/plat/imx/imx8qm/imx8qm_bl31_setup.c
@@ -49,11 +49,7 @@
};
static const mmap_region_t imx_mmap[] = {
- MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW),
- MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW),
- MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW),
- MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW),
- MAP_REGION_FLAT(PLAT_CCI_BASE, PLAT_CCI_SIZE, MT_DEVICE | MT_RW),
+ MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW),
{0}
};
@@ -324,6 +320,10 @@
/* turn on MU1 for non-secure OS/Hypervisor */
sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
+ /* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT_LPCG_BASE, mmio_read_32(IMX_GPT_LPCG_BASE) | (1 << 25));
/*
* create new partition for non-secure OS/Hypervisor
diff --git a/plat/imx/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c
index 833048d..bdba37c 100644
--- a/plat/imx/imx8qm/imx8qm_psci.c
+++ b/plat/imx/imx8qm/imx8qm_psci.c
@@ -17,6 +17,8 @@
#include <plat_imx8.h>
#include <sci/sci.h>
+#include "../../common/sci/imx8_mu.h"
+
#define CORE_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL0])
#define CLUSTER_PWR_STATE(state) \
@@ -29,44 +31,70 @@
SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
};
+/* save gic dist/redist context when GIC is poewr down */
+static struct plat_gic_ctx imx_gicv3_ctx;
+static unsigned int gpt_lpcg, gpt_reg[2];
+
+static void imx_enable_irqstr_wakeup(void)
+{
+ uint32_t irq_mask;
+ gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx;
+
+ /* put IRQSTR into ON mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* enable the irqsteer to handle wakeup irq */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1);
+ for (int i = 0; i < 15; i++) {
+ irq_mask = dist_ctx->gicd_isenabler[i];
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
+ }
+
+ /* set IRQSTR low power mode */
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
+ else
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+static void imx_disable_irqstr_wakeup(void)
+{
+ /* put IRQSTR into ON from STBY mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* disable the irqsteer */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0);
+ for (int i = 0; i < 16; i++)
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0);
+
+ /* put IRQSTR into OFF mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
int imx_pwr_domain_on(u_register_t mpidr)
{
int ret = PSCI_E_SUCCESS;
- unsigned int cluster_id, cpu_id;
-
- cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
- cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
- printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id);
+ sc_pm_set_resource_power_mode(ipc_handle, cluster_id == 0 ?
+ SC_R_A53 : SC_R_A72, SC_PM_PW_MODE_ON);
- if (cluster_id == 0) {
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53,
- SC_PM_PW_MODE_ON);
- if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
- SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
- ERROR("cluster0 core %d power on failed!\n", cpu_id);
- ret = PSCI_E_INTERN_FAIL;
- }
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
- if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id],
- true, BL31_BASE) != SC_ERR_NONE) {
- ERROR("boot cluster0 core %d failed!\n", cpu_id);
- ret = PSCI_E_INTERN_FAIL;
- }
- } else {
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72,
- SC_PM_PW_MODE_ON);
- if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4],
- SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
- ERROR(" cluster1 core %d power on failed!\n", cpu_id);
- ret = PSCI_E_INTERN_FAIL;
- }
+ if (sc_pm_set_resource_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
+ ERROR("core %d power on failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id);
+ ret = PSCI_E_INTERN_FAIL;
+ }
- if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id + 4],
- true, BL31_BASE) != SC_ERR_NONE) {
- ERROR("boot cluster1 core %d failed!\n", cpu_id);
- ret = PSCI_E_INTERN_FAIL;
- }
+ if (sc_pm_cpu_start(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ true, BL31_BASE) != SC_ERR_NONE) {
+ ERROR("boot core %d failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id);
+ ret = PSCI_E_INTERN_FAIL;
}
return ret;
@@ -91,11 +119,14 @@
plat_gic_cpuif_disable();
sc_pm_req_cpu_low_power_mode(ipc_handle,
- ap_core_index[cpu_id + cluster_id * 4],
- SC_PM_PW_MODE_OFF,
- SC_PM_WAKE_SRC_NONE);
- if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
- cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE);
+
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+ cci_disable_snoop_dvm_reqs(cluster_id);
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ }
printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id);
}
@@ -105,24 +136,148 @@
unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
- plat_gic_cpuif_disable();
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ plat_gic_cpuif_disable();
+ sc_pm_set_cpu_resume(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ true, BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+ } else {
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+ }
- cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ }
- sc_pm_set_cpu_resume_addr(ipc_handle,
- ap_core_index[cpu_id + cluster_id * 4], BL31_BASE);
- sc_pm_req_cpu_low_power_mode(ipc_handle,
- ap_core_index[cpu_id + cluster_id * 4],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ plat_gic_cpuif_disable();
+
+ /* save gic context */
+ plat_gic_save(cpu_id, &imx_gicv3_ctx);
+ /* enable the irqsteer for wakeup */
+ imx_enable_irqstr_wakeup();
+
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ /* Put GIC in LP mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
+ /* Save GPT clock and registers, then turn off its power */
+ gpt_lpcg = mmio_read_32(IMX_GPT_LPCG_BASE);
+ gpt_reg[0] = mmio_read_32(IMX_GPT_BASE);
+ gpt_reg[1] = mmio_read_32(IMX_GPT_BASE + 0x4);
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
+ sc_pm_set_cpu_resume(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ true, BL31_BASE);
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ else
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ }
}
void imx_domain_suspend_finish(const psci_power_state_t *target_state)
{
u_register_t mpidr = read_mpidr_el1();
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
- cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ /* check the system level status */
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ MU_Resume(SC_IPC_BASE);
- plat_gic_cpuif_enable();
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+
+ /* Put GIC/IRQSTR back to high power mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON);
+
+ /* Turn GPT power and restore its clock and registers */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT_BASE, gpt_reg[0]);
+ mmio_write_32(IMX_GPT_BASE + 0x4, gpt_reg[1]);
+ mmio_write_32(IMX_GPT_LPCG_BASE, gpt_lpcg);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
+
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
+
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ /* restore gic context */
+ plat_gic_restore(cpu_id, &imx_gicv3_ctx);
+ /* disable the irqsteer wakeup */
+ imx_disable_irqstr_wakeup();
+
+ plat_gic_cpuif_enable();
+ }
+
+ /* check the cluster level power status */
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+ }
+
+ /* check the core level power status */
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ sc_pm_set_cpu_resume(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ false, BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+ plat_gic_cpuif_enable();
+ } else {
+ write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+ isb();
+ }
}
int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
@@ -149,26 +304,23 @@
imx_mailbox_init(sec_entrypoint);
*psci_ops = &imx_plat_psci_ops;
- /* Request low power mode for cluster/cci, only need to do once */
- sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
- sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF);
- sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+ /* make sure system sources power ON in low power mode by default */
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
- /* Request RUN and LP modes for DDR, system interconnect etc. */
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
- SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
- SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
- SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
- SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
- SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
- SC_PM_PW_MODE_STBY);
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
- SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
- SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
return 0;
}
diff --git a/plat/imx/imx8qm/include/platform_def.h b/plat/imx/imx8qm/include/platform_def.h
index 1d0bdf9..946be76 100644
--- a/plat/imx/imx8qm/include/platform_def.h
+++ b/plat/imx/imx8qm/include/platform_def.h
@@ -36,22 +36,22 @@
#define BL31_LIMIT 0x80020000
#define PLAT_GICD_BASE 0x51a00000
-#define PLAT_GICD_SIZE 0x10000
#define PLAT_GICR_BASE 0x51b00000
-#define PLAT_GICR_SIZE 0xc0000
#define PLAT_CCI_BASE 0x52090000
-#define PLAT_CCI_SIZE 0x10000
#define CLUSTER0_CCI_SLVAE_IFACE 3
#define CLUSTER1_CCI_SLVAE_IFACE 4
#define IMX_BOOT_UART_BASE 0x5a060000
-#define IMX_BOOT_UART_SIZE 0x1000
#define IMX_BOOT_UART_BAUDRATE 115200
#define IMX_BOOT_UART_CLK_IN_HZ 24000000
#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
#define PLAT__CRASH_UART_CLK_IN_HZ 24000000
#define IMX_CONSOLE_BAUDRATE 115200
#define SC_IPC_BASE 0x5d1b0000
-#define SC_IPC_SIZE 0x10000
+#define IMX_GPT_LPCG_BASE 0x5d540000
+#define IMX_GPT_BASE 0x5d140000
+#define IMX_WUP_IRQSTR_BASE 0x51090000
+#define IMX_REG_BASE 0x50000000
+#define IMX_REG_SIZE 0x10000000
#define COUNTER_FREQUENCY 8000000 /* 8MHz */
diff --git a/plat/imx/imx8qm/include/sec_rsrc.h b/plat/imx/imx8qm/include/sec_rsrc.h
index a623cd3..d16d051 100644
--- a/plat/imx/imx8qm/include/sec_rsrc.h
+++ b/plat/imx/imx8qm/include/sec_rsrc.h
@@ -19,12 +19,14 @@
SC_R_GIC_SMMU,
SC_R_CCI,
SC_R_SYSTEM,
- SC_R_IRQSTR_SCU2
+ SC_R_IRQSTR_SCU2,
+ SC_R_GPT_0
};
/* resources that have register access for non-secure domain */
sc_rsrc_t ns_access_allowed[] = {
SC_R_GIC,
SC_R_GIC_SMMU,
- SC_R_CCI
+ SC_R_CCI,
+ SC_R_GPT_0
};
diff --git a/plat/imx/imx8qx/imx8qx_bl31_setup.c b/plat/imx/imx8qx/imx8qx_bl31_setup.c
index c90794a..bfe4052 100644
--- a/plat/imx/imx8qx/imx8qx_bl31_setup.c
+++ b/plat/imx/imx8qx/imx8qx_bl31_setup.c
@@ -44,10 +44,7 @@
(SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT))
static const mmap_region_t imx_mmap[] = {
- MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW),
- MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW),
- MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW),
- MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW),
+ MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW),
{0}
};
@@ -281,6 +278,11 @@
/* Turn on MU1 for non-secure OS/Hypervisor */
sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
+ /* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT0_LPCG_BASE, mmio_read_32(IMX_GPT0_LPCG_BASE) | (1 << 25));
+
/*
* create new partition for non-secure OS/Hypervisor
* uses global structs defined in sec_rsrc.h
diff --git a/plat/imx/imx8qx/imx8qx_psci.c b/plat/imx/imx8qx/imx8qx_psci.c
index 94c2e2b..aab3a2d 100644
--- a/plat/imx/imx8qx/imx8qx_psci.c
+++ b/plat/imx/imx8qx/imx8qx_psci.c
@@ -16,10 +16,52 @@
#include <plat_imx8.h>
#include <sci/sci.h>
+#include "../../common/sci/imx8_mu.h"
+
const static int ap_core_index[PLATFORM_CORE_COUNT] = {
SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3
};
+/* save gic dist/redist context when GIC is power down */
+static struct plat_gic_ctx imx_gicv3_ctx;
+static unsigned int gpt_lpcg, gpt_reg[2];
+
+static void imx_enable_irqstr_wakeup(void)
+{
+ uint32_t irq_mask;
+ gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx;
+
+ /* put IRQSTR into ON mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* enable the irqsteer to handle wakeup irq */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1);
+ for (int i = 0; i < 15; i++) {
+ irq_mask = dist_ctx->gicd_isenabler[i];
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
+ }
+
+ /* set IRQSTR low power mode */
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
+ else
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+static void imx_disable_irqstr_wakeup(void)
+{
+ /* Put IRQSTEER back to ON mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* disable the irqsteer */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0);
+ for (int i = 0; i < 16; i++)
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0);
+
+ /* Put IRQSTEER into OFF mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
int imx_pwr_domain_on(u_register_t mpidr)
{
int ret = PSCI_E_SUCCESS;
@@ -71,11 +113,52 @@
u_register_t mpidr = read_mpidr_el1();
unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
- plat_gic_cpuif_disable();
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) {
+ plat_gic_cpuif_disable();
+ sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+ } else {
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+ }
- sc_pm_set_cpu_resume_addr(ipc_handle, ap_core_index[cpu_id], BL31_BASE);
- sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
- SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1]))
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+
+ if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+ plat_gic_cpuif_disable();
+
+ /* save gic context */
+ plat_gic_save(cpu_id, &imx_gicv3_ctx);
+ /* enable the irqsteer for wakeup */
+ imx_enable_irqstr_wakeup();
+
+ /* Save GPT clock and registers, then turn off its power */
+ gpt_lpcg = mmio_read_32(IMX_GPT0_LPCG_BASE);
+ gpt_reg[0] = mmio_read_32(IMX_GPT0_BASE);
+ gpt_reg[1] = mmio_read_32(IMX_GPT0_BASE + 0x4);
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+
+ /* Put GIC in OFF mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
+ sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ else
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ }
}
void imx_domain_suspend_finish(const psci_power_state_t *target_state)
@@ -83,10 +166,51 @@
u_register_t mpidr = read_mpidr_el1();
unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
- sc_pm_req_low_power_mode(ipc_handle, ap_core_index[cpu_id],
- SC_PM_PW_MODE_ON);
+ if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+ MU_Resume(SC_IPC_BASE);
- plat_gic_cpuif_enable();
+ sc_pm_req_low_power_mode(ipc_handle, ap_core_index[cpu_id], SC_PM_PW_MODE_ON);
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+
+ /* Put GIC back to high power mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON);
+
+ /* restore gic context */
+ plat_gic_restore(cpu_id, &imx_gicv3_ctx);
+
+ /* Turn on GPT power and restore its clock and registers */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT0_BASE, gpt_reg[0]);
+ mmio_write_32(IMX_GPT0_BASE + 0x4, gpt_reg[1]);
+ mmio_write_32(IMX_GPT0_LPCG_BASE, gpt_lpcg);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+
+ /* disable the irqsteer wakeup */
+ imx_disable_irqstr_wakeup();
+
+ plat_gic_cpuif_enable();
+ }
+
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1]))
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
+
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) {
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+ plat_gic_cpuif_enable();
+ } else {
+ write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+ isb();
+ }
}
static const plat_psci_ops_t imx_plat_psci_ops = {
@@ -108,17 +232,15 @@
imx_mailbox_init(sec_entrypoint);
*psci_ops = &imx_plat_psci_ops;
- /* Request low power mode for A35 cluster, only need to do once */
- sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+ /* make sure system sources power ON in low power mode by default */
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
- /* Request RUN and LP modes for DDR, system interconnect etc. */
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
- SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
- SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
- sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
- SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
- SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
return 0;
}
diff --git a/plat/imx/imx8qx/include/platform_def.h b/plat/imx/imx8qx/include/platform_def.h
index 1239340..3a3fac8 100644
--- a/plat/imx/imx8qx/include/platform_def.h
+++ b/plat/imx/imx8qx/include/platform_def.h
@@ -37,18 +37,19 @@
#define MAX_MMAP_REGIONS 8
#define PLAT_GICD_BASE 0x51a00000
-#define PLAT_GICD_SIZE 0x10000
#define PLAT_GICR_BASE 0x51b00000
-#define PLAT_GICR_SIZE 0xc0000
#define IMX_BOOT_UART_BASE 0x5a060000
-#define IMX_BOOT_UART_SIZE 0x1000
#define IMX_BOOT_UART_BAUDRATE 115200
#define IMX_BOOT_UART_CLK_IN_HZ 24000000
#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
#define PLAT__CRASH_UART_CLK_IN_HZ 24000000
#define IMX_CONSOLE_BAUDRATE 115200
#define SC_IPC_BASE 0x5d1b0000
-#define SC_IPC_SIZE 0x10000
+#define IMX_GPT0_LPCG_BASE 0x5d540000
+#define IMX_GPT0_BASE 0x5d140000
+#define IMX_WUP_IRQSTR_BASE 0x51090000
+#define IMX_REG_BASE 0x50000000
+#define IMX_REG_SIZE 0x10000000
#define COUNTER_FREQUENCY 8000000
diff --git a/plat/imx/imx8qx/include/sec_rsrc.h b/plat/imx/imx8qx/include/sec_rsrc.h
index 37c9f66..b7fe0e8 100644
--- a/plat/imx/imx8qx/include/sec_rsrc.h
+++ b/plat/imx/imx8qx/include/sec_rsrc.h
@@ -14,10 +14,12 @@
SC_R_A35_3,
SC_R_GIC,
SC_R_SYSTEM,
- SC_R_IRQSTR_SCU2
+ SC_R_IRQSTR_SCU2,
+ SC_R_GPT_0
};
/* resources that have register access for non-secure domain */
sc_rsrc_t ns_access_allowed[] = {
SC_R_GIC,
+ SC_R_GPT_0
};
diff --git a/plat/marvell/a8k/common/include/a8k_plat_def.h b/plat/marvell/a8k/common/include/a8k_plat_def.h
index 7ed56e0..8b7cd64 100644
--- a/plat/marvell/a8k/common/include/a8k_plat_def.h
+++ b/plat/marvell/a8k/common/include/a8k_plat_def.h
@@ -53,12 +53,12 @@
0x440000 + ((n / 8) << 2))
#define MVEBU_CP_GPIO_DATA_OUT(cp_index, n) \
(MVEBU_CP_REGS_BASE(cp_index) + \
- 0x440100 + ((n > 32) ? 0x40 : 0x00))
+ 0x440100 + ((n > 31) ? 0x40 : 0x00))
#define MVEBU_CP_GPIO_DATA_OUT_EN(cp_index, n) \
(MVEBU_CP_REGS_BASE(cp_index) + \
- 0x440104 + ((n > 32) ? 0x40 : 0x00))
+ 0x440104 + ((n > 31) ? 0x40 : 0x00))
#define MVEBU_CP_GPIO_DATA_IN(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \
- 0x440110 + ((n > 32) ? 0x40 : 0x00))
+ 0x440110 + ((n > 31) ? 0x40 : 0x00))
#define MVEBU_AP_MPP_REGS(n) (MVEBU_RFU_BASE + 0x4000 + ((n) << 2))
#define MVEBU_AP_GPIO_REGS (MVEBU_RFU_BASE + 0x5040)
#define MVEBU_AP_GPIO_DATA_IN (MVEBU_AP_GPIO_REGS + 0x10)
diff --git a/plat/renesas/rcar/bl2_cpg_init.c b/plat/renesas/rcar/bl2_cpg_init.c
index 883fc9a..1dff690 100644
--- a/plat/renesas/rcar/bl2_cpg_init.c
+++ b/plat/renesas/rcar/bl2_cpg_init.c
@@ -28,7 +28,7 @@
static void bl2_system_cpg_init_m3n(void);
#endif
-#if (RCAR_LSI == RCAR_E3)
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_E3)
static void bl2_realtime_cpg_init_e3(void);
static void bl2_system_cpg_init_e3(void);
#endif
@@ -193,7 +193,7 @@
}
#endif
-#if (RCAR_LSI == RCAR_E3)
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_E3)
static void bl2_realtime_cpg_init_e3(void)
{
/* Realtime Module Stop Control Registers */
@@ -251,6 +251,9 @@
case RCAR_PRODUCT_M3N:
bl2_realtime_cpg_init_m3n();
break;
+ case RCAR_PRODUCT_E3:
+ bl2_realtime_cpg_init_e3();
+ break;
default:
panic();
break;
@@ -284,6 +287,9 @@
case RCAR_PRODUCT_M3N:
bl2_system_cpg_init_m3n();
break;
+ case RCAR_PRODUCT_E3:
+ bl2_system_cpg_init_e3();
+ break;
default:
panic();
break;
diff --git a/plat/renesas/rcar/include/rcar_def.h b/plat/renesas/rcar/include/rcar_def.h
index 1829e59..3bb03f2 100644
--- a/plat/renesas/rcar/include/rcar_def.h
+++ b/plat/renesas/rcar/include/rcar_def.h
@@ -204,8 +204,6 @@
#define EXTAL_MD14_MD13_TYPE_3 U(16666600) /* MD14=1 MD13=1 */
#define EXTAL_SALVATOR_XS U(8320000) /* Salvator-XS */
#define EXTAL_EBISU U(24000000) /* Ebisu */
-/* CPU Auxiliary Control Register */
-#define RCAR_CA57_DIS_LOAD_PASS_STORE (ULL(1) << 55)
/* CPG write protect registers */
#define CPGWPR_PASSWORD (0x5A5AFFFFU)
#define CPGWPCR_PASSWORD (0xA5A50000U)
diff --git a/plat/renesas/rcar/plat_pm.c b/plat/renesas/rcar/plat_pm.c
index 245a45a..47eda9a 100644
--- a/plat/renesas/rcar/plat_pm.c
+++ b/plat/renesas/rcar/plat_pm.c
@@ -175,7 +175,7 @@
uint64_t cpu = read_mpidr_el1() & 0x0000ffff;
int32_t rtn_on;
- rtn_on = cpu_on_check(cpu);
+ rtn_on = rcar_pwrc_cpu_on_check(cpu);
if (cpu == rcar_boot_mpidr)
panic();
diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk
index b9c0802..629a3cf 100644
--- a/plat/renesas/rcar/platform.mk
+++ b/plat/renesas/rcar/platform.mk
@@ -4,7 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
-PROGRAMMABLE_RESET_ADDRESS := 1
+PROGRAMMABLE_RESET_ADDRESS := 0
COLD_BOOT_SINGLE_CPU := 1
ARM_CCI_PRODUCT_ID := 500
TRUSTED_BOARD_BOOT := 1
diff --git a/plat/rockchip/common/rockchip_gicv2.c b/plat/rockchip/common/rockchip_gicv2.c
index 222a882..8db2b30 100644
--- a/plat/rockchip/common/rockchip_gicv2.c
+++ b/plat/rockchip/common/rockchip_gicv2.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
*/
@@ -22,11 +22,10 @@
#pragma weak plat_rockchip_gic_pcpu_init
/******************************************************************************
- * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
- * interrupts.
+ * List of interrupts.
*****************************************************************************/
static const interrupt_prop_t g0_interrupt_props[] = {
- PLAT_RK_GICV2_G1S_IRQS
+ PLAT_RK_GICV2_G0_IRQS
};
/*
diff --git a/plat/rockchip/rk3328/rk3328_def.h b/plat/rockchip/rk3328/rk3328_def.h
index 4704a72..0ce13ad 100644
--- a/plat/rockchip/rk3328/rk3328_def.h
+++ b/plat/rockchip/rk3328/rk3328_def.h
@@ -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
*/
@@ -131,15 +131,13 @@
#define RK_IRQ_SEC_SGI_7 15
/*
- * 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 a list of Group 0 interrupts.
*/
-#define PLAT_RK_GICV2_G1S_IRQS \
+#define PLAT_RK_GICV2_G0_IRQS \
INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
- GICV2_INTR_GROUP1, GIC_INTR_CFG_LEVEL), \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
- GICV2_INTR_GROUP1, GIC_INTR_CFG_LEVEL)
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/
#define SHARE_MEM_PAGE_NUM 15
diff --git a/plat/rockchip/rk3368/rk3368_def.h b/plat/rockchip/rk3368/rk3368_def.h
index a7be7c3..10ac77b 100644
--- a/plat/rockchip/rk3368/rk3368_def.h
+++ b/plat/rockchip/rk3368/rk3368_def.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
*/
@@ -96,12 +96,10 @@
#define RK_IRQ_SEC_SGI_7 15
/*
- * 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 a list of Group 0 interrupts.
*/
-#define PLAT_RK_GICV2_G1S_IRQS \
+#define PLAT_RK_GICV2_G0_IRQS \
INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
- GICV2_INTR_GROUP1, GIC_INTR_CFG_LEVEL)
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
#endif /* RK3368_DEF_H */
diff --git a/services/std_svc/spm/spci.c b/services/std_svc/spm/spci.c
index 44a0acd..1ee986a 100644
--- a/services/std_svc/spm/spci.c
+++ b/services/std_svc/spm/spci.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,7 @@
#include <string.h>
#include <common/debug.h>
+#include <common/runtime_svc.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/smccc.h>
#include <lib/spinlock.h>
@@ -679,9 +680,10 @@
/*******************************************************************************
* This function handles all SMCs in the range reserved for SPCI.
******************************************************************************/
-uint64_t spci_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
- uint64_t x3, uint64_t x4, void *cookie, void *handle,
- uint64_t flags)
+static uintptr_t spci_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 spci_fid;
@@ -773,3 +775,12 @@
WARN("SPCI: Unsupported call 0x%08x\n", smc_fid);
SMC_RET1(handle, SPCI_NOT_SUPPORTED);
}
+
+DECLARE_RT_SVC(
+ spci_handler,
+ OEN_SPCI_START,
+ OEN_SPCI_END,
+ SMC_TYPE_FAST,
+ NULL,
+ spci_smc_handler
+);
diff --git a/services/std_svc/spm/spm.mk b/services/std_svc/spm/spm.mk
index 4ba9feb..448aba4 100644
--- a/services/std_svc/spm/spm.mk
+++ b/services/std_svc/spm/spm.mk
@@ -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
#
@@ -26,8 +26,5 @@
INCLUDES += ${SPRT_LIB_INCLUDES}
-# Force SMC Calling Convention 2 when using SPM
-SMCCC_MAJOR_VERSION := 2
-
# Let the top-level Makefile know that we intend to include a BL32 image
NEED_BL32 := yes
diff --git a/services/std_svc/spm/sprt.c b/services/std_svc/spm/sprt.c
index f6af49f..8aa2a88 100644
--- a/services/std_svc/spm/sprt.c
+++ b/services/std_svc/spm/sprt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,6 +10,7 @@
#include <arch_helpers.h>
#include <common/debug.h>
+#include <common/runtime_svc.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/smccc.h>
#include <lib/utils.h>
@@ -154,9 +155,10 @@
/*******************************************************************************
* This function handles all SMCs in the range reserved for SPRT.
******************************************************************************/
-uint64_t sprt_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
- uint64_t x3, uint64_t x4, void *cookie, void *handle,
- uint64_t flags)
+static uintptr_t sprt_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)
{
/* SPRT only supported from the Secure world */
if (is_caller_non_secure(flags) == SMC_FROM_NON_SECURE) {
@@ -214,3 +216,12 @@
WARN("SPRT: Unsupported call 0x%08x\n", smc_fid);
SMC_RET1(handle, SPRT_NOT_SUPPORTED);
}
+
+DECLARE_RT_SVC(
+ sprt_handler,
+ OEN_SPRT_START,
+ OEN_SPRT_END,
+ SMC_TYPE_FAST,
+ NULL,
+ sprt_smc_handler
+);