Merge pull request #424 from jcastillo-arm/jc/tf-issues/327
IMF: postpone SCR_EL3 update if context is not initialized
diff --git a/Makefile b/Makefile
index ac059e8..6c062b2 100644
--- a/Makefile
+++ b/Makefile
@@ -262,6 +262,16 @@
include ${PLAT_MAKEFILE_FULL}
+# If the platform has not defined ENABLE_PLAT_COMPAT, then enable it by default
+ifndef ENABLE_PLAT_COMPAT
+ENABLE_PLAT_COMPAT := 1
+endif
+
+# Include the platform compatibility helpers for PSCI
+ifneq (${ENABLE_PLAT_COMPAT}, 0)
+include plat/compat/plat_compat.mk
+endif
+
# Include the CPU specific operations makefile. By default all CPU errata
# workarounds and CPU specifc optimisations are disabled. This can be
# overridden by the platform.
@@ -331,6 +341,7 @@
$(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
$(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
$(eval $(call assert_boolean,WARN_DEPRECATED))
+$(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
################################################################################
@@ -352,6 +363,7 @@
$(eval $(call add_define,PROGRAMMABLE_RESET_ADDRESS))
$(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
$(eval $(call add_define,WARN_DEPRECATED))
+$(eval $(call add_define,ENABLE_PLAT_COMPAT))
################################################################################
diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S
index ef390d4..0bd0485 100644
--- a/bl1/aarch64/bl1_exceptions.S
+++ b/bl1/aarch64/bl1_exceptions.S
@@ -195,7 +195,7 @@
b.ne unexpected_sync_exception
mov x0, x20
- bl display_boot_progress
+ bl bl1_print_bl31_ep_info
ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
msr elr_el3, x0
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index 50cf4e0..f62f31d 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -57,6 +57,9 @@
write_spsr_el3(bl2_ep->spsr);
write_elr_el3(bl2_ep->pc);
+ NOTICE("BL1: Booting BL2\n");
+ print_entry_point_info(bl2_ep);
+
eret(bl2_ep->args.arg0,
bl2_ep->args.arg1,
bl2_ep->args.arg2,
@@ -190,31 +193,18 @@
bl1_plat_set_bl2_ep_info(&bl2_image_info, &bl2_ep);
bl2_ep.args.arg1 = (unsigned long)bl2_tzram_layout;
- NOTICE("BL1: Booting BL2\n");
- INFO("BL1: BL2 address = 0x%llx\n",
- (unsigned long long) bl2_ep.pc);
- INFO("BL1: BL2 spsr = 0x%x\n", bl2_ep.spsr);
- VERBOSE("BL1: BL2 memory layout address = 0x%llx\n",
- (unsigned long long) bl2_tzram_layout);
-
bl1_run_bl2(&bl2_ep);
return;
}
/*******************************************************************************
- * Temporary function to print the fact that BL2 has done its job and BL31 is
- * about to be loaded. This is needed as long as printfs cannot be used
+ * Function called just before handing over to BL31 to inform the user about
+ * the boot progress. In debug mode, also print details about the BL31 image's
+ * execution context.
******************************************************************************/
-void display_boot_progress(entry_point_info_t *bl31_ep_info)
+void bl1_print_bl31_ep_info(const entry_point_info_t *bl31_ep_info)
{
NOTICE("BL1: Booting BL3-1\n");
- INFO("BL1: BL3-1 address = 0x%llx\n",
- (unsigned long long)bl31_ep_info->pc);
- INFO("BL1: BL3-1 spsr = 0x%llx\n",
- (unsigned long long)bl31_ep_info->spsr);
- INFO("BL1: BL3-1 params address = 0x%llx\n",
- (unsigned long long)bl31_ep_info->args.arg0);
- INFO("BL1: BL3-1 plat params address = 0x%llx\n",
- (unsigned long long)bl31_ep_info->args.arg1);
+ print_entry_point_info(bl31_ep_info);
}
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index a244a5c..9abc395 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -149,9 +149,7 @@
INFO("BL3-1: Preparing for EL3 exit to %s world\n",
(image_type == SECURE) ? "secure" : "normal");
- INFO("BL3-1: Next image address = 0x%llx\n",
- (unsigned long long) next_image_info->pc);
- INFO("BL3-1: Next image spsr = 0x%x\n", next_image_info->spsr);
+ print_entry_point_info(next_image_info);
cm_init_my_context(next_image_info);
cm_prepare_el3_exit(image_type);
}
diff --git a/common/bl_common.c b/common/bl_common.c
index 91a0ae8..0eeef83 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -151,11 +151,11 @@
uintptr_t image_handle;
uintptr_t image_spec;
size_t image_size = 0;
- int io_result = IO_FAIL;
+ 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 != IO_SUCCESS) {
+ if (io_result != 0) {
WARN("Failed to obtain reference to image id=%u (%i)\n",
image_id, io_result);
return 0;
@@ -163,7 +163,7 @@
/* Attempt to access the image */
io_result = io_open(dev_handle, image_spec, &image_handle);
- if (io_result != IO_SUCCESS) {
+ if (io_result != 0) {
WARN("Failed to access image id=%u (%i)\n",
image_id, io_result);
return 0;
@@ -171,7 +171,7 @@
/* Find the size of the image */
io_result = io_size(image_handle, &image_size);
- if ((io_result != IO_SUCCESS) || (image_size == 0)) {
+ if ((io_result != 0) || (image_size == 0)) {
WARN("Failed to determine the size of the image id=%u (%i)\n",
image_id, io_result);
}
@@ -352,3 +352,27 @@
return 0;
}
+
+/*******************************************************************************
+ * Print the content of an entry_point_info_t structure.
+ ******************************************************************************/
+void print_entry_point_info(const entry_point_info_t *ep_info)
+{
+ INFO("Entry point address = 0x%llx\n",
+ (unsigned long long) ep_info->pc);
+ INFO("SPSR = 0x%lx\n", (unsigned long) ep_info->spsr);
+
+#define PRINT_IMAGE_ARG(n) \
+ VERBOSE("Argument #" #n " = 0x%llx\n", \
+ (unsigned long long) ep_info->args.arg##n)
+
+ PRINT_IMAGE_ARG(0);
+ PRINT_IMAGE_ARG(1);
+ PRINT_IMAGE_ARG(2);
+ PRINT_IMAGE_ARG(3);
+ PRINT_IMAGE_ARG(4);
+ PRINT_IMAGE_ARG(5);
+ PRINT_IMAGE_ARG(6);
+ PRINT_IMAGE_ARG(7);
+#undef PRINT_IMAGE_ARG
+}
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 8f271cf..7987d10 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -1084,6 +1084,52 @@
* Install and run the Juno binaries on the board
* Obtain any other Juno software information
+### Testing SYSTEM SUSPEND on Juno
+
+The SYSTEM SUSPEND is a PSCI API which can be used to implement system suspend
+to RAM. For more details refer to section 5.16 of [PSCI]. The [Linaro releases]
+contains the required SCP and motherboard firmware support for this feature on
+Juno. The mainline linux kernel does not yet have support for this feature on
+Juno but it is queued to be merged in v4.4. Till that becomes available, the
+feature can be tested by using a custom kernel built from the following repo:
+
+ git clone git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git
+ cd linux
+ git checkout firmware/psci-1.0
+
+Configure the linux kernel:
+
+ export CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-linux-gnu-
+ make ARCH=arm64 defconfig
+
+The feature is tested conveniently by using the RTC. Enable the RTC driver in
+menuconfig
+
+ make ARCH=arm64 menuconfig
+
+The PL031 RTC driver can be enabled at the following location in menuconfig
+
+ ARM AMBA PL031 RTC
+ | Location:
+ | -> Device Drivers
+ | -> Real Time Clock
+
+Build the kernel
+
+ make ARCH=arm64 Image -j8
+
+Replace the kernel image in `SOFTWARE/` directory of Juno with the `Image` from
+arch/arm64/boot/ of the linux directory as explained in the
+[Juno Software Guide].
+
+Reset the board and wait for it to boot. At the shell prompt issue the
+following command:
+
+ echo +10 > /sys/class/rtc/rtc1/wakealarm
+ echo -n mem > /sys/power/state
+
+The Juno board should suspend to RAM and then wakeup after 10 seconds due to
+wakeup interrupt from RTC.
- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1098,4 +1144,5 @@
[DS-5]: http://www.arm.com/products/tools/software-tools/ds-5/index.php
[mbedTLS Repository]: https://github.com/ARMmbed/mbedtls.git
[Porting Guide]: ./porting-guide.md
+[PSCI]: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf "Power State Coordination Interface PDD (ARM DEN 0022C)"
[Trusted Board Boot]: trusted-board-boot.md
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 5a8a294..d291423 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -134,14 +134,14 @@
assert(dev_info != NULL);
*dev_info = (io_dev_info_t *)&fip_dev_info; /* cast away const */
- return IO_SUCCESS;
+ return 0;
}
/* Do some basic package checks. */
static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
{
- int result = IO_FAIL;
+ int result;
unsigned int image_id = (unsigned int)init_params;
uintptr_t backend_handle;
fip_toc_header_t header;
@@ -150,28 +150,28 @@
/* Obtain a reference to the image by querying the platform layer */
result = plat_get_image_source(image_id, &backend_dev_handle,
&backend_image_spec);
- if (result != IO_SUCCESS) {
+ if (result != 0) {
WARN("Failed to obtain reference to image id=%u (%i)\n",
image_id, result);
- result = IO_FAIL;
+ result = -ENOENT;
goto fip_dev_init_exit;
}
/* Attempt to access the FIP image */
result = io_open(backend_dev_handle, backend_image_spec,
&backend_handle);
- if (result != IO_SUCCESS) {
+ if (result != 0) {
WARN("Failed to access image id=%u (%i)\n", image_id, result);
- result = IO_FAIL;
+ result = -ENOENT;
goto fip_dev_init_exit;
}
result = io_read(backend_handle, (uintptr_t)&header, sizeof(header),
&bytes_read);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
if (!is_valid_header(&header)) {
WARN("Firmware Image Package header check failed.\n");
- result = IO_FAIL;
+ result = -ENOENT;
} else {
VERBOSE("FIP header looks OK.\n");
}
@@ -192,7 +192,7 @@
backend_dev_handle = (uintptr_t)NULL;
backend_image_spec = (uintptr_t)NULL;
- return IO_SUCCESS;
+ return 0;
}
@@ -200,7 +200,7 @@
static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity)
{
- int result = IO_FAIL;
+ int result;
uintptr_t backend_handle;
const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec;
size_t bytes_read;
@@ -217,23 +217,23 @@
*/
if (current_file.entry.offset_address != 0) {
WARN("fip_file_open : Only one open file at a time.\n");
- return IO_RESOURCES_EXHAUSTED;
+ return -ENOMEM;
}
/* Attempt to access the FIP image */
result = io_open(backend_dev_handle, backend_image_spec,
&backend_handle);
- if (result != IO_SUCCESS) {
+ if (result != 0) {
WARN("Failed to open Firmware Image Package (%i)\n", result);
- result = IO_FAIL;
+ result = -ENOENT;
goto fip_file_open_exit;
}
/* Seek past the FIP header into the Table of Contents */
result = io_seek(backend_handle, IO_SEEK_SET, sizeof(fip_toc_header_t));
- if (result != IO_SUCCESS) {
+ if (result != 0) {
WARN("fip_file_open: failed to seek\n");
- result = IO_FAIL;
+ result = -ENOENT;
goto fip_file_open_close;
}
@@ -243,7 +243,7 @@
(uintptr_t)¤t_file.entry,
sizeof(current_file.entry),
&bytes_read);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
if (compare_uuids(¤t_file.entry.uuid,
&uuid_spec->uuid) == 0) {
found_file = 1;
@@ -265,7 +265,7 @@
} else {
/* Did not find the file in the FIP. */
current_file.entry.offset_address = 0;
- result = IO_FAIL;
+ result = -ENOENT;
}
fip_file_open_close:
@@ -284,7 +284,7 @@
*length = ((file_state_t *)entity->info)->entry.size;
- return IO_SUCCESS;
+ return 0;
}
@@ -292,7 +292,7 @@
static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read)
{
- int result = IO_FAIL;
+ int result;
file_state_t *fp;
size_t file_offset;
size_t bytes_read;
@@ -306,9 +306,9 @@
/* Open the backend, attempt to access the blob image */
result = io_open(backend_dev_handle, backend_image_spec,
&backend_handle);
- if (result != IO_SUCCESS) {
+ if (result != 0) {
WARN("Failed to open FIP (%i)\n", result);
- result = IO_FAIL;
+ result = -ENOENT;
goto fip_file_read_exit;
}
@@ -317,17 +317,17 @@
/* Seek to the position in the FIP where the payload lives */
file_offset = fp->entry.offset_address + fp->file_pos;
result = io_seek(backend_handle, IO_SEEK_SET, file_offset);
- if (result != IO_SUCCESS) {
+ if (result != 0) {
WARN("fip_file_read: failed to seek\n");
- result = IO_FAIL;
+ result = -ENOENT;
goto fip_file_read_close;
}
result = io_read(backend_handle, buffer, length, &bytes_read);
- if (result != IO_SUCCESS) {
+ if (result != 0) {
/* We cannot read our data. Fail. */
WARN("Failed to read payload (%i)\n", result);
- result = IO_FAIL;
+ result = -ENOENT;
goto fip_file_read_close;
} else {
/* Set caller length and new file position. */
@@ -357,7 +357,7 @@
/* Clear the Entity info. */
entity->info = 0;
- return IO_SUCCESS;
+ return 0;
}
/* Exported functions */
@@ -365,11 +365,11 @@
/* Register the Firmware Image Package driver with the IO abstraction */
int register_io_dev_fip(const io_dev_connector_t **dev_con)
{
- int result = IO_FAIL;
+ int result;
assert(dev_con != NULL);
result = io_register_device(&fip_dev_info);
- if (result == IO_SUCCESS)
+ if (result == 0)
*dev_con = &fip_dev_connector;
return result;
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
index fc06fbb..d45107e 100644
--- a/drivers/io/io_memmap.c
+++ b/drivers/io/io_memmap.c
@@ -101,7 +101,7 @@
assert(dev_info != NULL);
*dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */
- return IO_SUCCESS;
+ return 0;
}
@@ -111,7 +111,7 @@
{
/* NOP */
/* TODO: Consider tracking open files and cleaning them up here */
- return IO_SUCCESS;
+ return 0;
}
@@ -120,7 +120,7 @@
static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity)
{
- int result = IO_FAIL;
+ int result = -ENOMEM;
const io_block_spec_t *block_spec = (io_block_spec_t *)spec;
/* Since we need to track open state for seek() we only allow one open
@@ -136,10 +136,9 @@
/* File cursor offset for seek and incremental reads etc. */
current_file.file_pos = 0;
entity->info = (uintptr_t)¤t_file;
- result = IO_SUCCESS;
+ result = 0;
} else {
WARN("A Memmap device is already active. Close first.\n");
- result = IO_RESOURCES_EXHAUSTED;
}
return result;
@@ -149,7 +148,7 @@
/* Seek to a particular file offset on the memmap device */
static int memmap_block_seek(io_entity_t *entity, int mode, ssize_t offset)
{
- int result = IO_FAIL;
+ int result = -ENOENT;
/* We only support IO_SEEK_SET for the moment. */
if (mode == IO_SEEK_SET) {
@@ -157,9 +156,7 @@
/* TODO: can we do some basic limit checks on seek? */
((file_state_t *)entity->info)->file_pos = offset;
- result = IO_SUCCESS;
- } else {
- result = IO_FAIL;
+ result = 0;
}
return result;
@@ -184,7 +181,7 @@
/* advance the file 'cursor' for incremental reads */
fp->file_pos += length;
- return IO_SUCCESS;
+ return 0;
}
@@ -207,7 +204,7 @@
/* advance the file 'cursor' for incremental writes */
fp->file_pos += length;
- return IO_SUCCESS;
+ return 0;
}
@@ -221,7 +218,7 @@
/* This would be a mem free() if we had malloc.*/
memset((void *)¤t_file, 0, sizeof(current_file));
- return IO_SUCCESS;
+ return 0;
}
@@ -230,11 +227,11 @@
/* Register the memmap driver with the IO abstraction */
int register_io_dev_memmap(const io_dev_connector_t **dev_con)
{
- int result = IO_FAIL;
+ int result;
assert(dev_con != NULL);
result = io_register_device(&memmap_dev_info);
- if (result == IO_SUCCESS)
+ if (result == 0)
*dev_con = &memmap_dev_connector;
return result;
diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c
index 8e62be1..63d0f68 100644
--- a/drivers/io/io_semihosting.c
+++ b/drivers/io/io_semihosting.c
@@ -84,10 +84,9 @@
static int sh_dev_open(const uintptr_t dev_spec __unused,
io_dev_info_t **dev_info)
{
- int result = IO_SUCCESS;
assert(dev_info != NULL);
*dev_info = (io_dev_info_t *)&sh_dev_info; /* cast away const */
- return result;
+ return 0;
}
@@ -95,7 +94,7 @@
static int sh_file_open(io_dev_info_t *dev_info __attribute__((unused)),
const uintptr_t spec, io_entity_t *entity)
{
- int result = IO_FAIL;
+ int result = -ENOENT;
long sh_result = -1;
const io_file_spec_t *file_spec = (const io_file_spec_t *)spec;
@@ -106,9 +105,7 @@
if (sh_result > 0) {
entity->info = (uintptr_t)sh_result;
- result = IO_SUCCESS;
- } else {
- result = IO_FAIL;
+ result = 0;
}
return result;
}
@@ -117,7 +114,6 @@
/* Seek to a particular file offset on the semi-hosting device */
static int sh_file_seek(io_entity_t *entity, int mode, ssize_t offset)
{
- int result = IO_FAIL;
long file_handle, sh_result;
assert(entity != NULL);
@@ -126,16 +122,14 @@
sh_result = semihosting_file_seek(file_handle, offset);
- result = (sh_result == 0) ? IO_SUCCESS : IO_FAIL;
-
- return result;
+ return (sh_result == 0) ? 0 : -ENOENT;
}
/* Return the size of a file on the semi-hosting device */
static int sh_file_len(io_entity_t *entity, size_t *length)
{
- int result = IO_FAIL;
+ int result = -ENOENT;
assert(entity != NULL);
assert(length != NULL);
@@ -144,7 +138,7 @@
long sh_result = semihosting_file_length(sh_handle);
if (sh_result >= 0) {
- result = IO_SUCCESS;
+ result = 0;
*length = (size_t)sh_result;
}
@@ -156,7 +150,7 @@
static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read)
{
- int result = IO_FAIL;
+ int result = -ENOENT;
long sh_result = -1;
size_t bytes = length;
long file_handle;
@@ -171,9 +165,8 @@
if (sh_result >= 0) {
*length_read = (bytes != length) ? bytes : length;
- result = IO_SUCCESS;
- } else
- result = IO_FAIL;
+ result = 0;
+ }
return result;
}
@@ -197,14 +190,13 @@
*length_written = length - bytes;
- return (sh_result == 0) ? IO_SUCCESS : IO_FAIL;
+ return (sh_result == 0) ? 0 : -ENOENT;
}
/* Close a file on the semi-hosting device */
static int sh_file_close(io_entity_t *entity)
{
- int result = IO_FAIL;
long sh_result = -1;
long file_handle;
@@ -214,9 +206,7 @@
sh_result = semihosting_file_close(file_handle);
- result = (sh_result >= 0) ? IO_SUCCESS : IO_FAIL;
-
- return result;
+ return (sh_result >= 0) ? 0 : -ENOENT;
}
@@ -225,11 +215,11 @@
/* Register the semi-hosting driver with the IO abstraction */
int register_io_dev_sh(const io_dev_connector_t **dev_con)
{
- int result = IO_FAIL;
+ int result;
assert(dev_con != NULL);
result = io_register_device(&sh_dev_info);
- if (result == IO_SUCCESS)
+ if (result == 0)
*dev_con = &sh_dev_connector;
return result;
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
index a3a8186..7cb1a6a 100644
--- a/drivers/io/io_storage.c
+++ b/drivers/io/io_storage.c
@@ -96,7 +96,7 @@
static int dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
io_dev_info_t **dev_info)
{
- int result = IO_FAIL;
+ int result;
assert(dev_info != NULL);
assert(is_valid_dev_connector(dev_con));
@@ -116,10 +116,10 @@
/* Locate an entity in the pool, specified by address */
static int find_first_entity(const io_entity_t *entity, unsigned int *index_out)
{
- int result = IO_FAIL;
+ int result = -ENOENT;
for (int index = 0; index < MAX_IO_HANDLES; ++index) {
if (entity_map[index] == entity) {
- result = IO_SUCCESS;
+ result = 0;
*index_out = index;
break;
}
@@ -131,17 +131,16 @@
/* Allocate an entity from the pool and return a pointer to it */
static int allocate_entity(io_entity_t **entity)
{
- int result = IO_FAIL;
+ int result = -ENOMEM;
assert(entity != NULL);
if (entity_count < MAX_IO_HANDLES) {
unsigned int index = 0;
result = find_first_entity(NULL, &index);
- assert(result == IO_SUCCESS);
+ assert(result == 0);
*entity = entity_map[index] = &entity_pool[index];
++entity_count;
- } else
- result = IO_RESOURCES_EXHAUSTED;
+ }
return result;
}
@@ -150,12 +149,12 @@
/* Release an entity back to the pool */
static int free_entity(const io_entity_t *entity)
{
- int result = IO_FAIL;
+ int result;
unsigned int index = 0;
assert(entity != NULL);
result = find_first_entity(entity, &index);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
entity_map[index] = NULL;
--entity_count;
}
@@ -169,15 +168,13 @@
/* Register a device driver */
int io_register_device(const io_dev_info_t *dev_info)
{
- int result = IO_FAIL;
+ int result = -ENOMEM;
assert(dev_info != NULL);
if (dev_count < MAX_IO_DEVICES) {
devices[dev_count] = dev_info;
dev_count++;
- result = IO_SUCCESS;
- } else {
- result = IO_RESOURCES_EXHAUSTED;
+ result = 0;
}
return result;
@@ -188,7 +185,7 @@
int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
uintptr_t *handle)
{
- int result = IO_FAIL;
+ int result;
assert(handle != NULL);
result = dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
@@ -200,18 +197,17 @@
* re-initialisation */
int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params)
{
- int result = IO_FAIL;
+ int result = 0;
assert(dev_handle != (uintptr_t)NULL);
assert(is_valid_dev(dev_handle));
io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
+ /* Absence of registered function implies NOP here */
if (dev->funcs->dev_init != NULL) {
result = dev->funcs->dev_init(dev, init_params);
- } else {
- /* Absence of registered function implies NOP here */
- result = IO_SUCCESS;
}
+
return result;
}
@@ -221,17 +217,15 @@
/* Close a connection to a device */
int io_dev_close(uintptr_t dev_handle)
{
- int result = IO_FAIL;
+ int result = 0;
assert(dev_handle != (uintptr_t)NULL);
assert(is_valid_dev(dev_handle));
io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
+ /* Absence of registered function implies NOP here */
if (dev->funcs->dev_close != NULL) {
result = dev->funcs->dev_close(dev);
- } else {
- /* Absence of registered function implies NOP here */
- result = IO_SUCCESS;
}
return result;
@@ -244,7 +238,7 @@
/* Open an IO entity */
int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle)
{
- int result = IO_FAIL;
+ int result;
assert((spec != (uintptr_t)NULL) && (handle != NULL));
assert(is_valid_dev(dev_handle));
@@ -253,11 +247,11 @@
result = allocate_entity(&entity);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
assert(dev->funcs->open != NULL);
result = dev->funcs->open(dev, spec, entity);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
entity->dev_handle = dev;
set_handle(handle, entity);
} else
@@ -270,7 +264,7 @@
/* Seek to a specific position in an IO entity */
int io_seek(uintptr_t handle, io_seek_mode_t mode, ssize_t offset)
{
- int result = IO_FAIL;
+ int result = -ENODEV;
assert(is_valid_entity(handle) && is_valid_seek_mode(mode));
io_entity_t *entity = (io_entity_t *)handle;
@@ -279,8 +273,6 @@
if (dev->funcs->seek != NULL)
result = dev->funcs->seek(entity, mode, offset);
- else
- result = IO_NOT_SUPPORTED;
return result;
}
@@ -289,7 +281,7 @@
/* Determine the length of an IO entity */
int io_size(uintptr_t handle, size_t *length)
{
- int result = IO_FAIL;
+ int result = -ENODEV;
assert(is_valid_entity(handle) && (length != NULL));
io_entity_t *entity = (io_entity_t *)handle;
@@ -298,8 +290,6 @@
if (dev->funcs->size != NULL)
result = dev->funcs->size(entity, length);
- else
- result = IO_NOT_SUPPORTED;
return result;
}
@@ -311,7 +301,7 @@
size_t length,
size_t *length_read)
{
- int result = IO_FAIL;
+ int result = -ENODEV;
assert(is_valid_entity(handle) && (buffer != (uintptr_t)NULL));
io_entity_t *entity = (io_entity_t *)handle;
@@ -320,8 +310,6 @@
if (dev->funcs->read != NULL)
result = dev->funcs->read(entity, buffer, length, length_read);
- else
- result = IO_NOT_SUPPORTED;
return result;
}
@@ -333,7 +321,7 @@
size_t length,
size_t *length_written)
{
- int result = IO_FAIL;
+ int result = -ENODEV;
assert(is_valid_entity(handle) && (buffer != (uintptr_t)NULL));
io_entity_t *entity = (io_entity_t *)handle;
@@ -343,8 +331,7 @@
if (dev->funcs->write != NULL) {
result = dev->funcs->write(entity, buffer, length,
length_written);
- } else
- result = IO_NOT_SUPPORTED;
+ }
return result;
}
@@ -353,19 +340,17 @@
/* Close an IO entity */
int io_close(uintptr_t handle)
{
- int result = IO_FAIL;
+ int result = 0;
assert(is_valid_entity(handle));
io_entity_t *entity = (io_entity_t *)handle;
io_dev_info_t *dev = entity->dev_handle;
+ /* Absence of registered function implies NOP here */
if (dev->funcs->close != NULL)
result = dev->funcs->close(entity);
- else {
- /* Absence of registered function implies NOP here */
- result = IO_SUCCESS;
- }
+
/* Ignore improbable free_entity failure */
(void)free_entity(entity);
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index c687b35..c9a7a3d 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -242,6 +242,8 @@
void reserve_mem(uint64_t *free_base, size_t *free_size,
uint64_t addr, size_t size);
+void print_entry_point_info(const entry_point_info_t *ep_info);
+
#endif /*__ASSEMBLY__*/
#endif /* __BL_COMMON_H__ */
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index 4c3526e..970ab2c 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -89,15 +89,6 @@
#define IO_MODE_RW (1 << 1)
-/* Return codes reported by 'io_*' APIs.
- * IMPORTANT: these definitions are deprecated. Callers should use standard
- * errno definitions when checking the return value of io_* APIs. */
-#define IO_SUCCESS (0)
-#define IO_FAIL (-ENOENT)
-#define IO_NOT_SUPPORTED (-ENODEV)
-#define IO_RESOURCES_EXHAUSTED (-ENOMEM)
-
-
/* Open a connection to a device */
int io_dev_open(const struct io_dev_connector *dev_con,
const uintptr_t dev_spec,
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index c236970..452c385 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -44,7 +44,8 @@
/* Special value used to verify platform parameters from BL2 to BL3-1 */
#define ARM_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
-#define ARM_CLUSTER_COUNT 2ull
+#define ARM_CLUSTER_COUNT 2
+#define ARM_SYSTEM_COUNT 1
#define ARM_CACHE_WRITEBACK_SHIFT 6
@@ -54,6 +55,7 @@
*/
#define ARM_PWR_LVL0 MPIDR_AFFLVL0
#define ARM_PWR_LVL1 MPIDR_AFFLVL1
+#define ARM_PWR_LVL2 MPIDR_AFFLVL2
/*
* Macros for local power states in ARM platforms encoded by State-ID field
@@ -179,10 +181,6 @@
#define ADDR_SPACE_SIZE (1ull << 32)
-#define PLAT_NUM_PWR_DOMAINS (ARM_CLUSTER_COUNT + \
- PLATFORM_CORE_COUNT)
-#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
-
/*
* This macro defines the deepest retention state possible. A higher state
* id will represent an invalid or a power down state.
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index ad41f4f..044e18e 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -35,6 +35,7 @@
#include <cassert.h>
#include <cpu_data.h>
#include <stdint.h>
+#include <xlat_tables.h>
/*
@@ -123,6 +124,11 @@
(((lvl1_state) << ARM_LOCAL_PSTATE_WIDTH) | \
arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+/* Make composite power state parameter till power level 2 */
+#define arm_make_pwrstate_lvl2(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl2_state) << (ARM_LOCAL_PSTATE_WIDTH * 2)) | \
+ arm_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type))
+
#endif /* __ARM_RECOM_STATE_ID_ENC__ */
@@ -135,10 +141,14 @@
/* Security utility functions */
void arm_tzc_setup(void);
+/* Systimer utility function */
+void arm_configure_sys_timer(void);
+
/* PM utility functions */
int arm_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state);
int arm_validate_ns_entrypoint(uintptr_t entrypoint);
+void arm_system_pwr_domain_resume(void);
/* Topology utility function */
int arm_check_mpidr(u_register_t mpidr);
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index c19df92..ea6a5d2 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -44,5 +44,6 @@
void __dead2 css_system_off(void);
void __dead2 css_system_reset(void);
void css_cpu_standby(plat_local_state_t cpu_state);
+void css_get_sys_suspend_power_state(psci_power_state_t *req_state);
#endif /* __CSS_PM_H__ */
diff --git a/plat/arm/board/fvp/fvp_io_storage.c b/plat/arm/board/fvp/fvp_io_storage.c
index e9d847f..0b74de2 100644
--- a/plat/arm/board/fvp/fvp_io_storage.c
+++ b/plat/arm/board/fvp/fvp_io_storage.c
@@ -114,14 +114,14 @@
static int open_semihosting(const uintptr_t spec)
{
- int result = IO_FAIL;
+ int result;
uintptr_t local_image_handle;
/* See if the file exists on semi-hosting.*/
result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
result = io_open(sh_dev_handle, spec, &local_image_handle);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
VERBOSE("Using Semi-hosting IO\n");
io_close(local_image_handle);
}
@@ -137,11 +137,11 @@
/* Register the additional IO devices on this platform */
io_result = register_io_dev_sh(&sh_dev_con);
- assert(io_result == IO_SUCCESS);
+ assert(io_result == 0);
/* Open connections to devices and cache the handles */
io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
- assert(io_result == IO_SUCCESS);
+ assert(io_result == 0);
/* Ignore improbable errors in release builds */
(void)io_result;
@@ -154,7 +154,7 @@
uintptr_t *image_spec)
{
int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
*dev_handle = sh_dev_handle;
*image_spec = (uintptr_t)&sh_file_spec[image_id];
}
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 840676c..9ada6b2 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -38,9 +38,13 @@
#include <v2m_def.h>
#include "../fvp_def.h"
+/* Required platform porting definitions */
+#define PLAT_NUM_PWR_DOMAINS (ARM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
/*
- * Most platform porting definitions provided by included headers
+ * Other platform porting definitions are provided by included headers
*/
/*
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index ba93254..39283c5 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -41,9 +41,13 @@
#include <v2m_def.h>
#include "../juno_def.h"
-
+/* Juno supports system power domain */
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2
+#define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \
+ ARM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
/*
- * Most platform porting definitions provided by included headers
+ * Other platform porting definitions are provided by included headers
*/
/*
diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c
new file mode 100644
index 0000000..4b956d2
--- /dev/null
+++ b/plat/arm/board/juno/juno_pm.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <css_pm.h>
+#include <plat_arm.h>
+
+/*
+ * Custom `validate_power_state` handler for Juno. According to PSCI
+ * Specification, interrupts targeted to cores in PSCI CPU SUSPEND should
+ * be able to resume it. On Juno, when the system power domain is suspended,
+ * the GIC is also powered down. The SCP resumes the final core to be suspend
+ * when an external wake-up event is received. But the other cores cannot be
+ * woken up by a targeted interrupt, because GIC doesn't forward these
+ * interrupts to the SCP. Due to this hardware limitation, we down-grade PSCI
+ * CPU SUSPEND requests targeted to the system power domain level
+ * to cluster power domain level.
+ *
+ * The system power domain suspend on Juno is only supported only via
+ * PSCI SYSTEM SUSPEND API.
+ */
+static int juno_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int rc;
+ rc = arm_validate_power_state(power_state, req_state);
+
+ /*
+ * Ensure that the system power domain level is never suspended
+ * via PSCI CPU SUSPEND API. Currently system suspend is only
+ * supported via PSCI SYSTEM SUSPEND API.
+ */
+ req_state->pwr_domain_state[ARM_PWR_LVL2] = ARM_LOCAL_STATE_RUN;
+ return rc;
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+const plat_psci_ops_t plat_arm_psci_pm_ops = {
+ .pwr_domain_on = css_pwr_domain_on,
+ .pwr_domain_on_finish = css_pwr_domain_on_finish,
+ .pwr_domain_off = css_pwr_domain_off,
+ .cpu_standby = css_cpu_standby,
+ .pwr_domain_suspend = css_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = css_pwr_domain_suspend_finish,
+ .system_off = css_system_off,
+ .system_reset = css_system_reset,
+ .validate_power_state = juno_validate_power_state,
+ .validate_ns_entrypoint = arm_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = css_get_sys_suspend_power_state
+};
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index b80cfb3..b711f3d 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -33,12 +33,16 @@
PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/aarch64/juno_helpers.S
BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \
- lib/cpus/aarch64/cortex_a57.S
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S
BL2_SOURCES += plat/arm/board/juno/juno_security.c \
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
- lib/cpus/aarch64/cortex_a57.S
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ plat/arm/board/juno/juno_pm.c \
+ plat/arm/board/juno/juno_security.c
# Enable workarounds for selected Cortex-A57 erratas.
ERRATA_A57_806969 := 0
diff --git a/plat/arm/common/aarch64/arm_common.c b/plat/arm/common/aarch64/arm_common.c
index 48b4ac8..4264183 100644
--- a/plat/arm/common/aarch64/arm_common.c
+++ b/plat/arm/common/aarch64/arm_common.c
@@ -32,6 +32,7 @@
#include <cci.h>
#include <mmio.h>
#include <plat_arm.h>
+#include <platform_def.h>
#include <xlat_tables.h>
@@ -142,3 +143,19 @@
{
cci_init(PLAT_ARM_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
}
+
+/*******************************************************************************
+ * Configures access to the system counter timer module.
+ ******************************************************************************/
+void arm_configure_sys_timer(void)
+{
+ unsigned int reg_val;
+
+ reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
+ reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
+ reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
+ mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTACR_BASE(PLAT_ARM_NSTIMER_FRAME_ID), reg_val);
+
+ reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
+ mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 899463e..923c333 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -40,7 +40,6 @@
#include <mmio.h>
#include <plat_arm.h>
#include <platform.h>
-#include <platform_def.h>
/*
@@ -197,8 +196,6 @@
******************************************************************************/
void arm_bl31_platform_setup(void)
{
- unsigned int reg_val;
-
/* Initialize the gic cpu and distributor interfaces */
plat_arm_gic_init();
arm_gic_setup();
@@ -217,13 +214,7 @@
CNTCR_FCREQ(0) | CNTCR_EN);
/* Allow access to the System counter timer module */
- reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
- reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
- reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
- mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTACR_BASE(PLAT_ARM_NSTIMER_FRAME_ID), reg_val);
-
- reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
- mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+ arm_configure_sys_timer();
/* Initialize power controller before setting up topology */
plat_arm_pwrc_setup();
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index 8488f12..ae67cde 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -220,9 +220,9 @@
/* See if a Firmware Image Package is available */
result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
result = io_open(fip_dev_handle, spec, &local_image_handle);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
VERBOSE("Using FIP\n");
io_close(local_image_handle);
}
@@ -237,9 +237,9 @@
uintptr_t local_image_handle;
result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
result = io_open(memmap_dev_handle, spec, &local_image_handle);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
VERBOSE("Using Memmap\n");
io_close(local_image_handle);
}
@@ -253,19 +253,19 @@
int io_result;
io_result = register_io_dev_fip(&fip_dev_con);
- assert(io_result == IO_SUCCESS);
+ assert(io_result == 0);
io_result = register_io_dev_memmap(&memmap_dev_con);
- assert(io_result == IO_SUCCESS);
+ assert(io_result == 0);
/* Open connections to devices and cache the handles */
io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
&fip_dev_handle);
- assert(io_result == IO_SUCCESS);
+ assert(io_result == 0);
io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
&memmap_dev_handle);
- assert(io_result == IO_SUCCESS);
+ assert(io_result == 0);
/* Ignore improbable errors in release builds */
(void)io_result;
@@ -282,7 +282,7 @@
uintptr_t *image_spec __attribute__((unused)))
{
/* By default do not try an alternative */
- return IO_FAIL;
+ return -ENOENT;
}
/* Return an IO device handle and specification which can be used to access
@@ -290,14 +290,14 @@
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
uintptr_t *image_spec)
{
- int result = IO_FAIL;
+ int result;
const struct plat_io_policy *policy;
assert(image_id < ARRAY_SIZE(policies));
policy = &policies[image_id];
result = policy->check(policy->image_spec);
- if (result == IO_SUCCESS) {
+ if (result == 0) {
*image_spec = policy->image_spec;
*dev_handle = *(policy->dev_handle);
} else {
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 2497588..d13d268 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -30,7 +30,9 @@
#include <arch_helpers.h>
#include <arm_def.h>
+#include <arm_gic.h>
#include <assert.h>
+#include <console.h>
#include <errno.h>
#include <plat_arm.h>
#include <platform_def.h>
@@ -148,6 +150,26 @@
return PSCI_E_INVALID_ADDRESS;
}
+/******************************************************************************
+ * Helper function to resume the platform from system suspend. Reinitialize
+ * the system components which are not in the Always ON power domain.
+ * TODO: Unify the platform setup when waking up from cold boot and system
+ * resume in arm_bl31_platform_setup().
+ *****************************************************************************/
+void arm_system_pwr_domain_resume(void)
+{
+ console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE);
+
+ /* Assert system power domain is available on the platform */
+ assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
+
+ arm_gic_setup();
+ plat_arm_security_setup();
+
+ arm_configure_sys_timer();
+}
+
/*******************************************************************************
* Private function to program the mailbox for a cpu before it is released
* from reset. This function assumes that the Trusted mail box base is within
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index c0c615b..3f46857 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -31,6 +31,7 @@
#include <arch_helpers.h>
#include <assert.h>
#include <arm_gic.h>
+#include <cassert.h>
#include <cci.h>
#include <css_pm.h>
#include <debug.h>
@@ -51,18 +52,30 @@
* The table must be terminated by a NULL entry.
*/
const unsigned int arm_pm_idle_states[] = {
- /* State-id - 0x01 */
- arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RET,
- ARM_PWR_LVL0, PSTATE_TYPE_STANDBY),
- /* State-id - 0x02 */
- arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF,
- ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
- /* State-id - 0x22 */
- arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
- ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x001 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RUN,
+ ARM_LOCAL_STATE_RET, ARM_PWR_LVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x002 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RUN,
+ ARM_LOCAL_STATE_OFF, ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x022 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF,
+ ARM_LOCAL_STATE_OFF, ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
+#if PLAT_MAX_PWR_LVL > ARM_PWR_LVL1
+ /* State-id - 0x222 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
+ ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
+#endif
0,
};
-#endif
+#endif /* __ARM_RECOM_STATE_ID_ENC__ */
+
+/*
+ * All the power management helpers in this file assume at least cluster power
+ * level is supported.
+ */
+CASSERT(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL1,
+ assert_max_pwr_lvl_supported_mismatch);
/*******************************************************************************
* Handler called when a power domain is about to be turned on. The
@@ -90,6 +103,16 @@
assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
ARM_LOCAL_STATE_OFF);
+ if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
+ /*
+ * Perform system initialization if woken up from system
+ * suspend.
+ */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
+ ARM_LOCAL_STATE_OFF)
+ arm_system_pwr_domain_resume();
+ }
+
/*
* Perform the common cluster specific operations i.e enable coherency
* if this cluster was off.
@@ -98,6 +121,18 @@
ARM_LOCAL_STATE_OFF)
cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+
+ if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
+ /*
+ * Skip GIC CPU interface and per-CPU Distributor interface
+ * setups if woken up from system suspend as it is done as
+ * part of css_system_pwr_domain_resume().
+ */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
+ ARM_LOCAL_STATE_OFF)
+ return;
+ }
+
/* Enable the gic cpu interface */
arm_gic_cpuif_setup();
@@ -114,10 +149,21 @@
static void css_power_down_common(const psci_power_state_t *target_state)
{
uint32_t cluster_state = scpi_power_on;
+ uint32_t system_state = scpi_power_on;
/* Prevent interrupts from spuriously waking up this cpu */
arm_gic_cpuif_deactivate();
+ if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
+ /*
+ * Check if power down at system power domain level is
+ * requested.
+ */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
+ ARM_LOCAL_STATE_OFF)
+ system_state = scpi_power_retention;
+ }
+
/* Cluster is to be turned off, so disable coherency */
if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
ARM_LOCAL_STATE_OFF) {
@@ -132,7 +178,7 @@
scpi_set_css_power_state(read_mpidr_el1(),
scpi_power_off,
cluster_state,
- scpi_power_on);
+ system_state);
}
/*******************************************************************************
@@ -246,6 +292,23 @@
}
/*******************************************************************************
+ * Handler called to return the 'req_state' for system suspend.
+ ******************************************************************************/
+void css_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ /*
+ * System Suspend is supported only if the system power domain node
+ * is implemented.
+ */
+ assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
+
+ for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF;
+}
+
+/*******************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform will take care of registering the handlers with PSCI.
******************************************************************************/
diff --git a/plat/arm/css/common/css_topology.c b/plat/arm/css/common/css_topology.c
index 381e786..03f81e6 100644
--- a/plat/arm/css/common/css_topology.c
+++ b/plat/arm/css/common/css_topology.c
@@ -31,26 +31,28 @@
#include <plat_arm.h>
/*
- * On ARM platforms, by default the cluster power level is treated as the
+ * On ARM CSS platforms, by default, the system power level is treated as the
* highest. The first entry in the power domain descriptor specifies the
- * number of cluster power domains i.e. 2.
+ * number of system power domains i.e. 1.
*/
-#define CSS_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_CLUSTER_COUNT
+#define CSS_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT
/*
- * The CSS power domain tree descriptor. The cluster power domains are
- * arranged so that when the PSCI generic code creates the power domain tree,
- * the indices of the CPU power domain nodes it allocates match the linear
- * indices returned by plat_core_pos_by_mpidr() i.e.
- * CLUSTER1 CPUs are allocated indices from 0 to 3 and the higher indices for
- * CLUSTER0 CPUs.
+ * The CSS power domain tree descriptor for dual cluster CSS platforms.
+ * The cluster power domains are arranged so that when the PSCI generic
+ * code creates the power domain tree, the indices of the CPU power
+ * domain nodes it allocates match the linear indices returned by
+ * plat_core_pos_by_mpidr() i.e. CLUSTER1 CPUs are allocated indices
+ * from 0 to 3 and the higher indices for CLUSTER0 CPUs.
*/
const unsigned char arm_power_domain_tree_desc[] = {
/* No of root nodes */
CSS_PWR_DOMAINS_AT_MAX_PWR_LVL,
- /* No of children for the first node */
+ /* No of children for the root node */
+ ARM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
PLAT_ARM_CLUSTER1_CORE_COUNT,
- /* No of children for the second node */
+ /* No of children for the second cluster node */
PLAT_ARM_CLUSTER0_CORE_COUNT
};
diff --git a/plat/arm/soc/common/soc_css.mk b/plat/arm/soc/common/soc_css.mk
index fd51b7f..d8a99a8 100644
--- a/plat/arm/soc/common/soc_css.mk
+++ b/plat/arm/soc/common/soc_css.mk
@@ -37,4 +37,4 @@
BL2_SOURCES += plat/arm/soc/common/soc_css_security.c
-#BL31_SOURCES +=
+BL31_SOURCES += plat/arm/soc/common/soc_css_security.c