Merge pull request #578 from EvanLloyd/ejll/woa_make2
Make improvements for host environment portability
diff --git a/Makefile b/Makefile
index 828ff57..b2ca916 100644
--- a/Makefile
+++ b/Makefile
@@ -199,7 +199,6 @@
common/aarch64/debug.S \
lib/aarch64/cache_helpers.S \
lib/aarch64/misc_helpers.S \
- lib/aarch64/xlat_helpers.c \
lib/stdlib/abort.c \
lib/stdlib/assert.c \
lib/stdlib/exit.c \
diff --git a/common/tf_printf.c b/common/tf_printf.c
index c1d4188..9a7667a 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -69,6 +69,7 @@
* %ld and %lld - signed 64 bit decimal format
* %lu and %llu - unsigned 64 bit decimal format
* %p - pointer format
+ * %z - size_t format
* Exits on all other formats.
*******************************************************************/
@@ -124,6 +125,11 @@
unsigned_num_print(unum, 16);
break;
+ case 'z':
+ if (sizeof(size_t) == 8)
+ bit64 = 1;
+ fmt++;
+ goto loop;
case 'l':
bit64 = 1;
fmt++;
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index f0adf57..3b6e242 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -76,12 +76,12 @@
A platform port must enable the Memory Management Unit (MMU) as well as the
instruction and data caches for each BL stage. Setting up the translation
tables is the responsibility of the platform port because memory maps differ
-across platforms. A memory translation library (see `lib/aarch64/xlat_helpers.c`
-and `lib/aarch64/xlat_tables.c`) is provided to help in this setup. Note that
-although this library supports non-identity mappings, this is intended only for
-re-mapping peripheral physical addresses and allows platforms with high I/O
-addresses to reduce their virtual address space. All other addresses
-corresponding to code and data must currently use an identity mapping.
+across platforms. A memory translation library (see `lib/aarch64/xlat_tables.c`)
+is provided to help in this setup. Note that although this library supports
+non-identity mappings, this is intended only for re-mapping peripheral physical
+addresses and allows platforms with high I/O addresses to reduce their virtual
+address space. All other addresses corresponding to code and data must currently
+use an identity mapping.
In ARM standard platforms, each BL stage configures the MMU in the
platform-specific architecture setup function, `blX_plat_arch_setup()`, and uses
@@ -633,6 +633,35 @@
to the ROTPK in the flags parameter.
+### Function: plat_get_nv_ctr()
+
+ Argument : void *, unsigned int *
+ Return : int
+
+This function is mandatory when Trusted Board Boot is enabled. It returns the
+non-volatile counter value stored in the platform in the second argument. The
+cookie in the first argument may be used to select the counter in case the
+platform provides more than one (for example, on platforms that use the default
+TBBR CoT, the cookie will correspond to the OID values defined in
+TRUSTED_FW_NVCOUNTER_OID or NON_TRUSTED_FW_NVCOUNTER_OID).
+
+The function returns 0 on success. Any other value means the counter value could
+not be retrieved from the platform.
+
+
+### Function: plat_set_nv_ctr()
+
+ Argument : void *, unsigned int
+ Return : int
+
+This function is mandatory when Trusted Board Boot is enabled. It sets a new
+counter value in the platform. The cookie in the first argument may be used to
+select the counter (as explained in plat_get_nv_ctr()).
+
+The function returns 0 on success. Any other value means the counter value could
+not be updated.
+
+
2.3 Common mandatory modifications
---------------------------------
@@ -1259,7 +1288,7 @@
### Function : plat_get_ns_image_entrypoint() [mandatory]
Argument : void
- Return : unsigned long
+ Return : uintptr_t
As previously described, BL2 is responsible for arranging for control to be
passed to a normal world BL image through BL31. This function returns the
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
new file mode 100644
index 0000000..ee6bf8d
--- /dev/null
+++ b/drivers/arm/tzc/tzc400.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2016, 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 <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stddef.h>
+#include <tzc400.h>
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_400_REGION_BASE_LOW_0_OFFSET 0x100
+#define TZC_400_REGION_BASE_HIGH_0_OFFSET 0x104
+#define TZC_400_REGION_TOP_LOW_0_OFFSET 0x108
+#define TZC_400_REGION_TOP_HIGH_0_OFFSET 0x10c
+#define TZC_400_REGION_ATTR_0_OFFSET 0x110
+#define TZC_400_REGION_ID_ACCESS_0_OFFSET 0x114
+
+/*
+ * Implementation defined values used to validate inputs later.
+ * Filters : max of 4 ; 0 to 3
+ * Regions : max of 9 ; 0 to 8
+ * Address width : Values between 32 to 64
+ */
+typedef struct tzc400_instance {
+ uintptr_t base;
+ uint8_t addr_width;
+ uint8_t num_filters;
+ uint8_t num_regions;
+} tzc400_instance_t;
+
+tzc400_instance_t tzc400;
+
+static inline unsigned int _tzc400_read_build_config(uintptr_t base)
+{
+ return mmio_read_32(base + BUILD_CONFIG_OFF);
+}
+
+static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base)
+{
+ return mmio_read_32(base + GATE_KEEPER_OFF);
+}
+
+static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val)
+{
+ mmio_write_32(base + GATE_KEEPER_OFF, val);
+}
+
+/*
+ * Get the open status information for all filter units.
+ */
+#define get_gate_keeper_os(base) ((_tzc400_read_gate_keeper(base) >> \
+ GATE_KEEPER_OS_SHIFT) & \
+ GATE_KEEPER_OS_MASK)
+
+
+/* Define common core functions used across different TZC peripherals. */
+DEFINE_TZC_COMMON_WRITE_ACTION(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
+
+static unsigned int _tzc400_get_gate_keeper(uintptr_t base,
+ unsigned int filter)
+{
+ unsigned int open_status;
+
+ open_status = get_gate_keeper_os(base);
+
+ return (open_status >> filter) & GATE_KEEPER_FILTER_MASK;
+}
+
+/* This function is not MP safe. */
+static void _tzc400_set_gate_keeper(uintptr_t base,
+ unsigned int filter,
+ int val)
+{
+ unsigned int open_status;
+
+ /* Upper half is current state. Lower half is requested state. */
+ open_status = get_gate_keeper_os(base);
+
+ if (val)
+ open_status |= (1 << filter);
+ else
+ open_status &= ~(1 << filter);
+
+ _tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) <<
+ GATE_KEEPER_OR_SHIFT);
+
+ /* Wait here until we see the change reflected in the TZC status. */
+ while ((get_gate_keeper_os(base)) != open_status)
+ ;
+}
+
+void tzc400_set_action(tzc_action_t action)
+{
+ assert(tzc400.base);
+ assert(action <= TZC_ACTION_ERR_INT);
+
+ /*
+ * - Currently no handler is provided to trap an error via interrupt
+ * or exception.
+ * - The interrupt action has not been tested.
+ */
+ _tzc400_write_action(tzc400.base, action);
+}
+
+void tzc400_init(uintptr_t base)
+{
+#if DEBUG
+ unsigned int tzc400_id;
+#endif
+ unsigned int tzc400_build;
+
+ assert(base);
+ tzc400.base = base;
+
+#if DEBUG
+ tzc400_id = _tzc_read_peripheral_id(base);
+ if (tzc400_id != TZC_400_PERIPHERAL_ID) {
+ ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id);
+ panic();
+ }
+#endif
+
+ /* Save values we will use later. */
+ tzc400_build = _tzc400_read_build_config(tzc400.base);
+ tzc400.num_filters = ((tzc400_build >> BUILD_CONFIG_NF_SHIFT) &
+ BUILD_CONFIG_NF_MASK) + 1;
+ tzc400.addr_width = ((tzc400_build >> BUILD_CONFIG_AW_SHIFT) &
+ BUILD_CONFIG_AW_MASK) + 1;
+ tzc400.num_regions = ((tzc400_build >> BUILD_CONFIG_NR_SHIFT) &
+ BUILD_CONFIG_NR_MASK) + 1;
+}
+
+/*
+ * `tzc400_configure_region0` is used to program region 0 into the TrustZone
+ * controller. Region 0 covers the whole address space that is not mapped
+ * to any other region, and is enabled on all filters; this cannot be
+ * changed. This function only changes the access permissions.
+ */
+void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access)
+{
+ assert(tzc400.base);
+ assert(sec_attr <= TZC_REGION_S_RDWR);
+
+ _tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access);
+}
+
+/*
+ * `tzc400_configure_region` is used to program regions into the TrustZone
+ * controller. A region can be associated with more than one filter. The
+ * associated filters are passed in as a bitmap (bit0 = filter0).
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc400_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc400_configure_region(unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions)
+{
+ assert(tzc400.base);
+
+ /* Do range checks on filters and regions. */
+ assert(((filters >> tzc400.num_filters) == 0) &&
+ (region >= 0) && (region < tzc400.num_regions));
+
+ /*
+ * Do address range check based on TZC configuration. A 64bit address is
+ * the max and expected case.
+ */
+ assert(((region_top <= (UINT64_MAX >> (64 - tzc400.addr_width))) &&
+ (region_base < region_top)));
+
+ /* region_base and (region_top + 1) must be 4KB aligned */
+ assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+ assert(sec_attr <= TZC_REGION_S_RDWR);
+
+ _tzc400_configure_region(tzc400.base, filters, region, region_base,
+ region_top,
+ sec_attr, nsaid_permissions);
+}
+
+void tzc400_enable_filters(void)
+{
+ unsigned int state;
+ unsigned int filter;
+
+ assert(tzc400.base);
+
+ for (filter = 0; filter < tzc400.num_filters; filter++) {
+ state = _tzc400_get_gate_keeper(tzc400.base, filter);
+ if (state) {
+ /* The TZC filter is already configured. Changing the
+ * programmer's view in an active system can cause
+ * unpredictable behavior therefore panic for now rather
+ * than try to determine whether this is safe in this
+ * instance. See:
+ * http://infocenter.arm.com/help/index.jsp?\
+ * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
+ ERROR("TZC-400 : Filter %d Gatekeeper already"
+ " enabled.\n", filter);
+ panic();
+ }
+ _tzc400_set_gate_keeper(tzc400.base, filter, 1);
+ }
+}
+
+void tzc400_disable_filters(void)
+{
+ unsigned int filter;
+
+ assert(tzc400.base);
+
+ /*
+ * We don't do the same state check as above as the Gatekeepers are
+ * disabled after reset.
+ */
+ for (filter = 0; filter < tzc400.num_filters; filter++)
+ _tzc400_set_gate_keeper(tzc400.base, filter, 0);
+}
diff --git a/drivers/arm/tzc/tzc_common_private.c b/drivers/arm/tzc/tzc_common_private.c
new file mode 100644
index 0000000..f570daf
--- /dev/null
+++ b/drivers/arm/tzc/tzc_common_private.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, 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 <mmio.h>
+#include <tzc_common.h>
+
+#define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_action( \
+ uintptr_t base, \
+ tzc_action_t action) \
+ { \
+ mmio_write_32(base + TZC_##macro_name##_ACTION_OFF, \
+ action); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_base( \
+ uintptr_t base, \
+ int region_no, \
+ uintptr_t region_base) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET, \
+ (unsigned int)region_base); \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET, \
+ (unsigned int)(region_base >> 32)); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_top( \
+ uintptr_t base, \
+ int region_no, \
+ uintptr_t region_top) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET \
+ (TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET, \
+ (unsigned int)region_top); \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET, \
+ (unsigned int)(region_top >> 32)); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_attributes( \
+ uintptr_t base, \
+ int region_no, \
+ unsigned int attr) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_ATTR_0_OFFSET, \
+ attr); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_id_access( \
+ uintptr_t base, \
+ int region_no, \
+ unsigned int val) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET, \
+ val); \
+ }
+
+/*
+ * It is used to program region 0 ATTRIBUTES and ACCESS register.
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name) \
+ void _tzc##fn_name##_configure_region0(uintptr_t base, \
+ tzc_region_attributes_t sec_attr, \
+ unsigned int ns_device_access) \
+ { \
+ assert(base); \
+ VERBOSE("TrustZone : Configuring region 0 " \
+ "(TZC Interface Base=%p sec_attr=0x%x," \
+ " ns_devs=0x%x)\n", (void *)base, \
+ sec_attr, ns_device_access); \
+ \
+ /* Set secure attributes on region 0 */ \
+ _tzc##fn_name##_write_region_attributes(base, 0, \
+ sec_attr << TZC_REGION_ATTR_SEC_SHIFT); \
+ \
+ /***************************************************/ \
+ /* Specify which non-secure devices have permission*/ \
+ /* to access region 0. */ \
+ /***************************************************/ \
+ _tzc##fn_name##_write_region_id_access(base, \
+ 0, \
+ ns_device_access); \
+ }
+
+/*
+ * It is used to program a region from 1 to 8 in the TrustZone controller.
+ * NOTE:
+ * Region 0 is special; it is preferable to use
+ * ##fn_name##_configure_region0 for this region (see comment for
+ * that function).
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name) \
+ void _tzc##fn_name##_configure_region(uintptr_t base, \
+ unsigned int filters, \
+ int region_no, \
+ uintptr_t region_base, \
+ uintptr_t region_top, \
+ tzc_region_attributes_t sec_attr, \
+ unsigned int nsaid_permissions) \
+ { \
+ assert(base); \
+ VERBOSE("TrustZone : Configuring region " \
+ "(TZC Interface Base: %p, region_no = %d)" \
+ "...\n", (void *)base, region_no); \
+ VERBOSE("TrustZone : ... base = %p, top = %p," \
+ "\n", (void *)region_base, (void *)region_top);\
+ VERBOSE("TrustZone : ... sec_attr = 0x%x," \
+ " ns_devs = 0x%x)\n", \
+ sec_attr, nsaid_permissions); \
+ \
+ /***************************************************/ \
+ /* Inputs look ok, start programming registers. */ \
+ /* All the address registers are 32 bits wide and */ \
+ /* have a LOW and HIGH */ \
+ /* component used to construct an address up to a */ \
+ /* 64bit. */ \
+ /***************************************************/ \
+ _tzc##fn_name##_write_region_base(base, \
+ region_no, region_base); \
+ _tzc##fn_name##_write_region_top(base, \
+ region_no, region_top); \
+ \
+ /* Enable filter to the region and set secure attributes */\
+ _tzc##fn_name##_write_region_attributes(base, \
+ region_no, \
+ (sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\
+ (filters << TZC_REGION_ATTR_F_EN_SHIFT));\
+ \
+ /***************************************************/ \
+ /* Specify which non-secure devices have permission*/ \
+ /* to access this region. */ \
+ /***************************************************/ \
+ _tzc##fn_name##_write_region_id_access(base, \
+ region_no, \
+ nsaid_permissions); \
+ }
+
+#if DEBUG
+static unsigned int _tzc_read_peripheral_id(uintptr_t base)
+{
+ unsigned int id;
+
+ id = mmio_read_32(base + PID0_OFF);
+ /* Masks DESC part in PID1 */
+ id |= ((mmio_read_32(base + PID1_OFF) & 0xF) << 8);
+
+ return id;
+}
+#endif
diff --git a/drivers/arm/tzc/tzc_dmc500.c b/drivers/arm/tzc/tzc_dmc500.c
new file mode 100644
index 0000000..16a53a4
--- /dev/null
+++ b/drivers/arm/tzc/tzc_dmc500.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2016, 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 <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <tzc_dmc500.h>
+#include "tzc_common.h"
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_DMC500_REGION_BASE_LOW_0_OFFSET 0x054
+#define TZC_DMC500_REGION_BASE_HIGH_0_OFFSET 0x058
+#define TZC_DMC500_REGION_TOP_LOW_0_OFFSET 0x05C
+#define TZC_DMC500_REGION_TOP_HIGH_0_OFFSET 0x060
+#define TZC_DMC500_REGION_ATTR_0_OFFSET 0x064
+#define TZC_DMC500_REGION_ID_ACCESS_0_OFFSET 0x068
+
+#define TZC_DMC500_ACTION_OFF 0x50
+
+/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */
+static const tzc_dmc500_driver_data_t *g_driver_data;
+
+#define verify_region_attr(region, attr) \
+ ((g_conf_regions[(region)].sec_attr == \
+ ((attr) >> TZC_REGION_ATTR_SEC_SHIFT)) \
+ && ((attr) & (0x1 << TZC_REGION_ATTR_F_EN_SHIFT)))
+
+/*
+ * Structure for configured regions attributes in DMC500.
+ */
+typedef struct tzc_dmc500_regions {
+ tzc_region_attributes_t sec_attr;
+ int is_enabled;
+} tzc_dmc500_regions_t;
+
+/*
+ * Array storing the attributes of the configured regions. This array
+ * will be used by the `tzc_dmc500_verify_complete` to verify the flush
+ * completion.
+ */
+static tzc_dmc500_regions_t g_conf_regions[MAX_REGION_VAL + 1];
+
+/* Helper Macros for making the code readable */
+#define DMC_INST_BASE_ADDR(instance) (g_driver_data->dmc_base[instance])
+#define DMC_INST_SI_BASE(instance, interface) \
+ (DMC_INST_BASE_ADDR(instance) + IFACE_OFFSET(interface))
+
+DEFINE_TZC_COMMON_WRITE_ACTION(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(_dmc500, DMC500)
+
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(_dmc500)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(_dmc500)
+
+static inline unsigned int _tzc_dmc500_read_region_attr_0(
+ uintptr_t dmc_si_base,
+ int region_no)
+{
+ return mmio_read_32(dmc_si_base +
+ TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) +
+ TZC_DMC500_REGION_ATTR_0_OFFSET);
+}
+
+static inline void _tzc_dmc500_write_flush_control(uintptr_t dmc_si_base)
+{
+ mmio_write_32(dmc_si_base + SI_FLUSH_CTRL_OFFSET, 1);
+}
+
+/*
+ * Sets the Flush controls for all the DMC Instances and System Interfaces.
+ * This initiates the flush of configuration settings from the shadow
+ * registers to the actual configuration register. The caller should poll
+ * changed register to confirm update.
+ */
+void tzc_dmc500_config_complete(void)
+{
+ int dmc_inst, sys_if;
+
+ assert(g_driver_data);
+
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ _tzc_dmc500_write_flush_control(
+ DMC_INST_SI_BASE(dmc_inst, sys_if));
+ }
+}
+
+/*
+ * This function reads back the secure attributes from the configuration
+ * register for each DMC Instance and System Interface and compares it with
+ * the configured value. The successful verification of the region attributes
+ * confirms that the flush operation has completed.
+ * If the verification fails, the caller is expected to invoke this API again
+ * till it succeeds.
+ * Returns 0 on success and 1 on failure.
+ */
+int tzc_dmc500_verify_complete(void)
+{
+ int dmc_inst, sys_if, region_no;
+ unsigned int attr;
+
+ assert(g_driver_data);
+ /* Region 0 must be configured */
+ assert(g_conf_regions[0].is_enabled);
+
+ /* Iterate over all configured regions */
+ for (region_no = 0; region_no <= MAX_REGION_VAL; region_no++) {
+ if (!g_conf_regions[region_no].is_enabled)
+ continue;
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count;
+ dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT;
+ sys_if++) {
+ attr = _tzc_dmc500_read_region_attr_0(
+ DMC_INST_SI_BASE(dmc_inst, sys_if),
+ region_no);
+ VERBOSE("Verifying DMC500 region:%d"
+ " dmc_inst:%d sys_if:%d attr:%x\n",
+ region_no, dmc_inst, sys_if, attr);
+ if (!verify_region_attr(region_no, attr))
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * `tzc_dmc500_configure_region0` is used to program region 0 in both the
+ * system interfaces of all the DMC-500 instances. Region 0 covers the whole
+ * address space that is not mapped to any other region for a system interface,
+ * and is always enabled; this cannot be changed. This function only changes
+ * the access permissions.
+ */
+void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions)
+{
+ int dmc_inst, sys_if;
+
+ /* Assert if DMC-500 is not initialized */
+ assert(g_driver_data);
+
+ /* Configure region_0 in all DMC instances */
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ _tzc_dmc500_configure_region0(
+ DMC_INST_SI_BASE(dmc_inst, sys_if),
+ sec_attr, nsaid_permissions);
+ }
+
+ g_conf_regions[0].sec_attr = sec_attr;
+ g_conf_regions[0].is_enabled = 1;
+}
+
+/*
+ * `tzc_dmc500_configure_region` is used to program a region into all system
+ * interfaces of all the DMC instances.
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc_dmc500_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc_dmc500_configure_region(int region_no,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions)
+{
+ int dmc_inst, sys_if;
+
+ assert(g_driver_data);
+ /* Do range checks on regions. */
+ assert(region_no >= 0 && region_no <= MAX_REGION_VAL);
+
+ /*
+ * Do address range check based on DMC-TZ configuration. A 43bit address
+ * is the max and expected case.
+ */
+ assert(((region_top <= (UINT64_MAX >> (64 - 43))) &&
+ (region_base < region_top)));
+
+ /* region_base and (region_top + 1) must be 4KB aligned */
+ assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ _tzc_dmc500_configure_region(
+ DMC_INST_SI_BASE(dmc_inst, sys_if),
+ TZC_DMC500_REGION_ATTR_F_EN_MASK,
+ region_no, region_base, region_top,
+ sec_attr, nsaid_permissions);
+ }
+
+ g_conf_regions[region_no].sec_attr = sec_attr;
+ g_conf_regions[region_no].is_enabled = 1;
+}
+
+/* Sets the action value for all the DMC instances */
+void tzc_dmc500_set_action(tzc_action_t action)
+{
+ int dmc_inst;
+
+ assert(g_driver_data);
+
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ /*
+ * - Currently no handler is provided to trap an error via
+ * interrupt or exception.
+ * - The interrupt action has not been tested.
+ */
+ _tzc_dmc500_write_action(DMC_INST_BASE_ADDR(dmc_inst), action);
+ }
+}
+
+/*
+ * A DMC-500 instance must be present at each base address provided by the
+ * platform. It also expects platform to pass at least one instance of
+ * DMC-500.
+ */
+static void validate_plat_driver_data(
+ const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+#if DEBUG
+ int i;
+ unsigned int dmc_id;
+ uintptr_t dmc_base;
+
+ assert(plat_driver_data);
+ assert(plat_driver_data->dmc_count > 0 &&
+ (plat_driver_data->dmc_count <= MAX_DMC_COUNT));
+
+ for (i = 0; i < plat_driver_data->dmc_count; i++) {
+ dmc_base = plat_driver_data->dmc_base[i];
+ assert(dmc_base);
+
+ dmc_id = _tzc_read_peripheral_id(dmc_base);
+ assert(dmc_id == DMC500_PERIPHERAL_ID);
+ }
+#endif /* DEBUG */
+}
+
+
+/*
+ * Initializes the base address and count of DMC instances.
+ *
+ * Note : Only pointer to plat_driver_data is saved, so it is caller's
+ * responsibility to keep it valid until the driver is used.
+ */
+void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+ /* Check valid pointer is passed */
+ assert(plat_driver_data);
+
+ /*
+ * NOTE: This driver expects the DMC-500 controller is already in
+ * READY state. Hence, it uses the reconfiguration method for
+ * programming TrustZone regions
+ */
+ /* Validates the information passed by platform */
+ validate_plat_driver_data(plat_driver_data);
+ g_driver_data = plat_driver_data;
+}
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
index 7194443..97adf81 100644
--- a/drivers/arm/tzc400/tzc400.c
+++ b/drivers/arm/tzc400/tzc400.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -28,313 +28,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <assert.h>
-#include <debug.h>
-#include <mmio.h>
-#include <stddef.h>
-#include <tzc400.h>
-
-/*
- * Implementation defined values used to validate inputs later.
- * Filters : max of 4 ; 0 to 3
- * Regions : max of 9 ; 0 to 8
- * Address width : Values between 32 to 64
- */
-typedef struct tzc_instance {
- uintptr_t base;
- uint8_t addr_width;
- uint8_t num_filters;
- uint8_t num_regions;
-} tzc_instance_t;
-
-tzc_instance_t tzc;
-
-
-static inline uint32_t tzc_read_build_config(uintptr_t base)
-{
- return mmio_read_32(base + BUILD_CONFIG_OFF);
-}
-
-static inline uint32_t tzc_read_gate_keeper(uintptr_t base)
-{
- return mmio_read_32(base + GATE_KEEPER_OFF);
-}
-
-static inline void tzc_write_gate_keeper(uintptr_t base, uint32_t val)
-{
- mmio_write_32(base + GATE_KEEPER_OFF, val);
-}
-
-static inline void tzc_write_action(uintptr_t base, tzc_action_t action)
-{
- mmio_write_32(base + ACTION_OFF, action);
-}
-
-static inline void tzc_write_region_base_low(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_BASE_LOW_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_base_high(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_BASE_HIGH_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_low(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_TOP_LOW_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_high(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_TOP_HIGH_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_attributes(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_ATTRIBUTES_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_id_access(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_ID_ACCESS_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static unsigned int tzc_read_peripheral_id(uintptr_t base)
-{
- unsigned int id;
-
- id = mmio_read_8(base + PID0_OFF);
- /* Masks jep106_id_3_0 part in PID1 */
- id |= ((mmio_read_8(base + PID1_OFF) & 0xF) << 8);
-
- return id;
-}
-
-static uint32_t tzc_get_gate_keeper(uintptr_t base, uint8_t filter)
-{
- uint32_t tmp;
-
- tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
- GATE_KEEPER_OS_MASK;
-
- return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
-}
-
-/* This function is not MP safe. */
-static void tzc_set_gate_keeper(uintptr_t base, uint8_t filter, uint32_t val)
-{
- uint32_t tmp;
-
- /* Upper half is current state. Lower half is requested state. */
- tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
- GATE_KEEPER_OS_MASK;
-
- if (val)
- tmp |= (1 << filter);
- else
- tmp &= ~(1 << filter);
-
- tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
- GATE_KEEPER_OR_SHIFT);
-
- /* Wait here until we see the change reflected in the TZC status. */
- while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
- GATE_KEEPER_OS_MASK) != tmp)
- ;
-}
-
-
-void tzc_init(uintptr_t base)
-{
- unsigned int tzc_id;
- unsigned int tzc_build;
-
- assert(base);
-
- tzc.base = base;
-
- /*
- * We expect to see a tzc400. Check peripheral ID.
- */
- tzc_id = tzc_read_peripheral_id(tzc.base);
- if (tzc_id != TZC400_PERIPHERAL_ID) {
- ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
- panic();
- }
-
- /* Save values we will use later. */
- tzc_build = tzc_read_build_config(tzc.base);
- tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
- BUILD_CONFIG_NF_MASK) + 1;
- tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
- BUILD_CONFIG_AW_MASK) + 1;
- tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
- BUILD_CONFIG_NR_MASK) + 1;
-}
-
-/*
- * `tzc_configure_region0` is used to program region 0 into the TrustZone
- * controller. Region 0 covers the whole address space that is not mapped
- * to any other region, and is enabled on all filters; this cannot be
- * changed. This function only changes the access permissions.
- */
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access)
-{
- assert(tzc.base);
-
- VERBOSE("TZC : Configuring region 0 (sec_attr=0x%x, ns_devs=0x%x)\n",
- sec_attr, ns_device_access);
-
- assert(sec_attr <= TZC_REGION_S_RDWR);
-
- /* Set secure attributes on region 0 */
- tzc_write_region_attributes(tzc.base, 0,
- sec_attr << REG_ATTR_SEC_SHIFT);
-
- /*
- * Specify which non-secure devices have permission to access
- * region 0.
- */
- tzc_write_region_id_access(tzc.base, 0, ns_device_access);
-}
-
-
-/*
- * `tzc_configure_region` is used to program regions into the TrustZone
- * controller. A region can be associated with more than one filter. The
- * associated filters are passed in as a bitmap (bit0 = filter0).
- * NOTE:
- * Region 0 is special; it is preferable to use tzc_configure_region0
- * for this region (see comment for that function).
- */
-void tzc_configure_region(uint32_t filters,
- uint8_t region,
- uint64_t region_base,
- uint64_t region_top,
- tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access)
-{
- assert(tzc.base);
-
- VERBOSE("TZC : Configuring region (filters=0x%x, region=%d, ...\n",
- filters, region);
- VERBOSE("TZC : ... base=0x%lx, top=0x%lx, ...\n",
- region_base, region_top);
- VERBOSE("TZC : ... sec_attr=0x%x, ns_devs=0x%x)\n",
- sec_attr, ns_device_access);
-
- /* Do range checks on filters and regions. */
- assert(((filters >> tzc.num_filters) == 0) &&
- (region < tzc.num_regions));
-
- /*
- * Do address range check based on TZC configuration. A 64bit address is
- * the max and expected case.
- */
- assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
- (region_base < region_top)));
-
- /* region_base and (region_top + 1) must be 4KB aligned */
- assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
-
- assert(sec_attr <= TZC_REGION_S_RDWR);
-
- /*
- * Inputs look ok, start programming registers.
- * All the address registers are 32 bits wide and have a LOW and HIGH
- * component used to construct a up to a 64bit address.
- */
- tzc_write_region_base_low(tzc.base, region,
- (uint32_t)(region_base));
- tzc_write_region_base_high(tzc.base, region,
- (uint32_t)(region_base >> 32));
-
- tzc_write_region_top_low(tzc.base, region,
- (uint32_t)(region_top));
- tzc_write_region_top_high(tzc.base, region,
- (uint32_t)(region_top >> 32));
-
- /* Assign the region to a filter and set secure attributes */
- tzc_write_region_attributes(tzc.base, region,
- (sec_attr << REG_ATTR_SEC_SHIFT) | filters);
-
- /*
- * Specify which non-secure devices have permission to access this
- * region.
- */
- tzc_write_region_id_access(tzc.base, region, ns_device_access);
-}
-
-
-void tzc_set_action(tzc_action_t action)
-{
- assert(tzc.base);
-
- /*
- * - Currently no handler is provided to trap an error via interrupt
- * or exception.
- * - The interrupt action has not been tested.
- */
- tzc_write_action(tzc.base, action);
-}
-
-
-void tzc_enable_filters(void)
-{
- uint32_t state;
- uint32_t filter;
-
- assert(tzc.base);
-
- for (filter = 0; filter < tzc.num_filters; filter++) {
- state = tzc_get_gate_keeper(tzc.base, filter);
- if (state) {
- /* The TZC filter is already configured. Changing the
- * programmer's view in an active system can cause
- * unpredictable behavior therefore panic for now rather
- * than try to determine whether this is safe in this
- * instance. See:
- * http://infocenter.arm.com/help/index.jsp?\
- * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
- ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
- filter);
- panic();
- }
- tzc_set_gate_keeper(tzc.base, filter, 1);
- }
-}
-
-
-void tzc_disable_filters(void)
-{
- uint32_t filter;
-
- assert(tzc.base);
-
- /*
- * We don't do the same state check as above as the Gatekeepers are
- * disabled after reset.
- */
- for (filter = 0; filter < tzc.num_filters; filter++)
- tzc_set_gate_keeper(tzc.base, filter, 0);
-}
+#if ERROR_DEPRECATED
+#error "Using deprecated TZC-400 source file"
+#else
+#include "../tzc/tzc400.c"
+#endif /* ERROR_DEPRECATED */
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index bdd3c5a..4184556 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -40,6 +40,9 @@
#include <stdint.h>
#include <string.h>
+/* ASN.1 tags */
+#define ASN1_INTEGER 0x02
+
#define return_if_error(rc) \
do { \
if (rc != 0) { \
@@ -227,6 +230,83 @@
}
/*
+ * Authenticate by Non-Volatile counter
+ *
+ * To protect the system against rollback, the platform includes a non-volatile
+ * counter whose value can only be increased. All certificates include a counter
+ * value that should not be lower than the value stored in the platform. If the
+ * value is larger, the counter in the platform must be updated to the new
+ * value.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
+ const auth_img_desc_t *img_desc,
+ void *img, unsigned int img_len)
+{
+ char *p;
+ void *data_ptr = NULL;
+ unsigned int data_len, len, i;
+ unsigned int cert_nv_ctr, plat_nv_ctr;
+ int rc = 0;
+
+ /* Get the counter value from current image. The AM expects the IPM
+ * to return the counter value as a DER encoded integer */
+ rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr,
+ img, img_len, &data_ptr, &data_len);
+ return_if_error(rc);
+
+ /* Parse the DER encoded integer */
+ assert(data_ptr);
+ p = (char *)data_ptr;
+ if (*p != ASN1_INTEGER) {
+ /* Invalid ASN.1 integer */
+ return 1;
+ }
+ p++;
+
+ /* NV-counters are unsigned integers up to 32-bit */
+ len = (unsigned int)(*p & 0x7f);
+ if ((*p & 0x80) || (len > 4)) {
+ return 1;
+ }
+ p++;
+
+ /* Check the number is not negative */
+ if (*p & 0x80) {
+ return 1;
+ }
+
+ /* Convert to unsigned int. This code is for a little-endian CPU */
+ cert_nv_ctr = 0;
+ for (i = 0; i < len; i++) {
+ cert_nv_ctr = (cert_nv_ctr << 8) | *p++;
+ }
+
+ /* Get the counter from the platform */
+ rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr);
+ return_if_error(rc);
+
+ if (cert_nv_ctr < plat_nv_ctr) {
+ /* Invalid NV-counter */
+ return 1;
+ } else if (cert_nv_ctr > plat_nv_ctr) {
+ if (img_desc->parent == NULL) {
+ /* This certificate has been signed with the ROT key.
+ * Update the platform counter value */
+ rc = plat_set_nv_ctr(param->plat_nv_ctr->cookie,
+ cert_nv_ctr);
+ return_if_error(rc);
+ } else {
+ /* Secondary certificates cannot modify the counter */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
* Return the parent id in the output parameter '*parent_id'
*
* Return value:
@@ -310,6 +390,10 @@
rc = auth_signature(&auth_method->param.sig,
img_desc, img_ptr, img_len);
break;
+ case AUTH_METHOD_NV_CTR:
+ rc = auth_nvctr(&auth_method->param.nv_ctr,
+ img_desc, img_ptr, img_len);
+ break;
default:
/* Unknown authentication method */
rc = 1;
diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c
index 52e6971..1a6a9a7 100644
--- a/drivers/auth/mbedtls/mbedtls_x509_parser.c
+++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c
@@ -405,6 +405,13 @@
/*
* Extract an authentication parameter from an X509v3 certificate
+ *
+ * This function returns a pointer to the extracted data and its length.
+ * Depending on the type of parameter, a pointer to the data stored in the
+ * certificate may be returned (i.e. an octet string containing a hash). Other
+ * data may need to be copied and formatted (i.e. integers). In the later case,
+ * a buffer of the correct type needs to be statically allocated, filled and
+ * returned.
*/
static int get_auth_param(const auth_param_type_desc_t *type_desc,
void *img, unsigned int img_len,
@@ -422,6 +429,7 @@
*param_len = (unsigned int)tbs.len;
break;
case AUTH_PARAM_HASH:
+ case AUTH_PARAM_NV_CTR:
/* All these parameters are included as X509v3 extensions */
rc = get_ext(type_desc->cookie, param, param_len);
break;
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index 6023c78..dae35d1 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -56,6 +56,11 @@
/*
* Parameter type descriptors
*/
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+
static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, 0);
static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
@@ -116,6 +121,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -158,6 +170,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -193,6 +212,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -218,6 +244,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -260,6 +293,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -285,6 +325,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -327,6 +374,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -352,6 +406,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -394,6 +455,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &non_trusted_nv_ctr,
+ .plat_nv_ctr = &non_trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -419,6 +487,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &non_trusted_nv_ctr,
+ .plat_nv_ctr = &non_trusted_nv_ctr
+ }
}
},
.authenticated_data = {
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index f8e1664..3085688 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -31,178 +31,179 @@
#ifndef __TZC400_H__
#define __TZC400_H__
+#include <tzc_common.h>
-#define BUILD_CONFIG_OFF 0x000
-#define ACTION_OFF 0x004
-#define GATE_KEEPER_OFF 0x008
-#define SPECULATION_CTRL_OFF 0x00c
-#define INT_STATUS 0x010
-#define INT_CLEAR 0x014
+#define BUILD_CONFIG_OFF 0x000
+#define GATE_KEEPER_OFF 0x008
+#define SPECULATION_CTRL_OFF 0x00c
+#define INT_STATUS 0x010
+#define INT_CLEAR 0x014
-#define FAIL_ADDRESS_LOW_OFF 0x020
-#define FAIL_ADDRESS_HIGH_OFF 0x024
-#define FAIL_CONTROL_OFF 0x028
-#define FAIL_ID 0x02c
+#define FAIL_ADDRESS_LOW_OFF 0x020
+#define FAIL_ADDRESS_HIGH_OFF 0x024
+#define FAIL_CONTROL_OFF 0x028
+#define FAIL_ID 0x02c
-#define REGION_BASE_LOW_OFF 0x100
-#define REGION_BASE_HIGH_OFF 0x104
-#define REGION_TOP_LOW_OFF 0x108
-#define REGION_TOP_HIGH_OFF 0x10c
-#define REGION_ATTRIBUTES_OFF 0x110
-#define REGION_ID_ACCESS_OFF 0x114
-#define REGION_NUM_OFF(region) (0x20 * region)
+/* ID registers not common across different varieties of TZC */
+#define PID5 0xFD4
+#define PID6 0xFD8
+#define PID7 0xFDC
-/* ID Registers */
-#define PID0_OFF 0xfe0
-#define PID1_OFF 0xfe4
-#define PID2_OFF 0xfe8
-#define PID3_OFF 0xfec
-#define PID4_OFF 0xfd0
-#define PID5_OFF 0xfd4
-#define PID6_OFF 0xfd8
-#define PID7_OFF 0xfdc
-#define CID0_OFF 0xff0
-#define CID1_OFF 0xff4
-#define CID2_OFF 0xff8
-#define CID3_OFF 0xffc
-
-#define BUILD_CONFIG_NF_SHIFT 24
-#define BUILD_CONFIG_NF_MASK 0x3
-#define BUILD_CONFIG_AW_SHIFT 8
-#define BUILD_CONFIG_AW_MASK 0x3f
-#define BUILD_CONFIG_NR_SHIFT 0
-#define BUILD_CONFIG_NR_MASK 0x1f
-
-/* Not describing the case where regions 1 to 8 overlap */
-#define ACTION_RV_SHIFT 0
-#define ACTION_RV_MASK 0x3
-#define ACTION_RV_LOWOK 0x0
-#define ACTION_RV_LOWERR 0x1
-#define ACTION_RV_HIGHOK 0x2
-#define ACTION_RV_HIGHERR 0x3
+#define BUILD_CONFIG_NF_SHIFT 24
+#define BUILD_CONFIG_NF_MASK 0x3
+#define BUILD_CONFIG_AW_SHIFT 8
+#define BUILD_CONFIG_AW_MASK 0x3f
+#define BUILD_CONFIG_NR_SHIFT 0
+#define BUILD_CONFIG_NR_MASK 0x1f
/*
* Number of gate keepers is implementation defined. But we know the max for
* this device is 4. Get implementation details from BUILD_CONFIG.
*/
-#define GATE_KEEPER_OS_SHIFT 16
-#define GATE_KEEPER_OS_MASK 0xf
-#define GATE_KEEPER_OR_SHIFT 0
-#define GATE_KEEPER_OR_MASK 0xf
-#define GATE_KEEPER_FILTER_MASK 0x1
+#define GATE_KEEPER_OS_SHIFT 16
+#define GATE_KEEPER_OS_MASK 0xf
+#define GATE_KEEPER_OR_SHIFT 0
+#define GATE_KEEPER_OR_MASK 0xf
+#define GATE_KEEPER_FILTER_MASK 0x1
/* Speculation is enabled by default. */
-#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
-#define SPECULATION_CTRL_READ_DISABLE (1 << 0)
+#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
+#define SPECULATION_CTRL_READ_DISABLE (1 << 0)
/* Max number of filters allowed is 4. */
-#define INT_STATUS_OVERLAP_SHIFT 16
-#define INT_STATUS_OVERLAP_MASK 0xf
-#define INT_STATUS_OVERRUN_SHIFT 8
-#define INT_STATUS_OVERRUN_MASK 0xf
-#define INT_STATUS_STATUS_SHIFT 0
-#define INT_STATUS_STATUS_MASK 0xf
+#define INT_STATUS_OVERLAP_SHIFT 16
+#define INT_STATUS_OVERLAP_MASK 0xf
+#define INT_STATUS_OVERRUN_SHIFT 8
+#define INT_STATUS_OVERRUN_MASK 0xf
+#define INT_STATUS_STATUS_SHIFT 0
+#define INT_STATUS_STATUS_MASK 0xf
-#define INT_CLEAR_CLEAR_SHIFT 0
-#define INT_CLEAR_CLEAR_MASK 0xf
+#define INT_CLEAR_CLEAR_SHIFT 0
+#define INT_CLEAR_CLEAR_MASK 0xf
-#define FAIL_CONTROL_DIR_SHIFT (1 << 24)
-#define FAIL_CONTROL_DIR_READ 0x0
-#define FAIL_CONTROL_DIR_WRITE 0x1
-#define FAIL_CONTROL_NS_SHIFT (1 << 21)
-#define FAIL_CONTROL_NS_SECURE 0x0
-#define FAIL_CONTROL_NS_NONSECURE 0x1
-#define FAIL_CONTROL_PRIV_SHIFT (1 << 20)
-#define FAIL_CONTROL_PRIV_PRIV 0x0
-#define FAIL_CONTROL_PRIV_UNPRIV 0x1
+#define FAIL_CONTROL_DIR_SHIFT (1 << 24)
+#define FAIL_CONTROL_DIR_READ 0x0
+#define FAIL_CONTROL_DIR_WRITE 0x1
+#define FAIL_CONTROL_NS_SHIFT (1 << 21)
+#define FAIL_CONTROL_NS_SECURE 0x0
+#define FAIL_CONTROL_NS_NONSECURE 0x1
+#define FAIL_CONTROL_PRIV_SHIFT (1 << 20)
+#define FAIL_CONTROL_PRIV_PRIV 0x0
+#define FAIL_CONTROL_PRIV_UNPRIV 0x1
/*
* FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific.
* Platform should provide the value on initialisation.
*/
-#define FAIL_ID_VNET_SHIFT 24
-#define FAIL_ID_VNET_MASK 0xf
-#define FAIL_ID_ID_SHIFT 0
-
-/* Used along with 'tzc_region_attributes_t' below */
-#define REG_ATTR_SEC_SHIFT 30
-#define REG_ATTR_F_EN_SHIFT 0
-#define REG_ATTR_F_EN_MASK 0xf
-#define REG_ATTR_FILTER_BIT(x) ((1 << x) << REG_ATTR_F_EN_SHIFT)
-#define REG_ATTR_FILTER_BIT_ALL (REG_ATTR_F_EN_MASK << \
- REG_ATTR_F_EN_SHIFT)
+#define FAIL_ID_VNET_SHIFT 24
+#define FAIL_ID_VNET_MASK 0xf
+#define FAIL_ID_ID_SHIFT 0
-#define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT 16
-#define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT 0
-#define REGION_ID_ACCESS_NSAID_ID_MASK 0xf
+#define TZC_400_PERIPHERAL_ID 0x460
+/* Filter enable bits in a TZC */
+#define TZC_400_REGION_ATTR_F_EN_MASK 0xf
+#define TZC_400_REGION_ATTR_FILTER_BIT(x) ((1 << x) \
+ << TZC_REGION_ATTR_F_EN_SHIFT)
+#define TZC_400_REGION_ATTR_FILTER_BIT_ALL \
+ (TZC_400_REGION_ATTR_F_EN_MASK << \
+ TZC_REGION_ATTR_F_EN_SHIFT)
-/* Macros for setting Region ID access permissions based on NSAID */
-#define TZC_REGION_ACCESS_RD(id) \
- ((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
- REGION_ID_ACCESS_NSAID_RD_EN_SHIFT)
-#define TZC_REGION_ACCESS_WR(id) \
- ((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
- REGION_ID_ACCESS_NSAID_WR_EN_SHIFT)
-#define TZC_REGION_ACCESS_RDWR(id) \
- (TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id))
-
-/* Consist of part_number_1 and part_number_0 */
-#define TZC400_PERIPHERAL_ID 0x0460
-
+/*
+ * Define some macros for backward compatibility with existing tzc400 clients.
+ */
+#if !ERROR_DEPRECATED
+#define REG_ATTR_FILTER_BIT(x) ((1 << x) \
+ << TZC_REGION_ATTR_F_EN_SHIFT)
+#define REG_ATTR_FILTER_BIT_ALL (TZC_400_REGION_ATTR_F_EN_MASK << \
+ TZC_REGION_ATTR_F_EN_SHIFT)
+#endif /* __ERROR_DEPRECATED__ */
+/*
+ * All TZC region configuration registers are placed one after another. It
+ * depicts size of block of registers for programming each region.
+ */
+#define TZC_400_REGION_SIZE 0x20
+#define TZC_400_ACTION_OFF 0x4
#ifndef __ASSEMBLY__
+#include <cdefs.h>
#include <stdint.h>
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
+void tzc400_init(uintptr_t base);
+void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access);
+void tzc400_configure_region(unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access);
+void tzc400_set_action(tzc_action_t action);
+void tzc400_enable_filters(void);
+void tzc400_disable_filters(void);
/*
- * What type of action is expected when an access violation occurs.
- * The memory requested is zeroed. But we can also raise and event to
- * let the system know it happened.
- * We can raise an interrupt(INT) and/or cause an exception(ERR).
- * TZC_ACTION_NONE - No interrupt, no Exception
- * TZC_ACTION_ERR - No interrupt, raise exception -> sync external
- * data abort
- * TZC_ACTION_INT - Raise interrupt, no exception
- * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
- * external data abort
+ * Deprecated APIs
*/
-typedef enum {
- TZC_ACTION_NONE = 0,
- TZC_ACTION_ERR = 1,
- TZC_ACTION_INT = 2,
- TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
-} tzc_action_t;
-
-/*
- * Controls secure access to a region. If not enabled secure access is not
- * allowed to region.
- */
-typedef enum {
- TZC_REGION_S_NONE = 0,
- TZC_REGION_S_RD = 1,
- TZC_REGION_S_WR = 2,
- TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
-} tzc_region_attributes_t;
+static inline void tzc_init(uintptr_t base) __deprecated;
+static inline void tzc_configure_region0(
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access) __deprecated;
+static inline void tzc_configure_region(
+ unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access) __deprecated;
+static inline void tzc_set_action(tzc_action_t action) __deprecated;
+static inline void tzc_enable_filters(void) __deprecated;
+static inline void tzc_disable_filters(void) __deprecated;
+static inline void tzc_init(uintptr_t base)
+{
+ tzc400_init(base);
+}
-void tzc_init(uintptr_t base);
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access);
-void tzc_configure_region(uint32_t filters,
- uint8_t region,
- uint64_t region_base,
- uint64_t region_top,
+static inline void tzc_configure_region0(
tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access);
-void tzc_enable_filters(void);
-void tzc_disable_filters(void);
-void tzc_set_action(tzc_action_t action);
+ unsigned int ns_device_access)
+{
+ tzc400_configure_region0(sec_attr, ns_device_access);
+}
+
+static inline void tzc_configure_region(
+ unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access)
+{
+ tzc400_configure_region(filters, region, region_base,
+ region_top, sec_attr, ns_device_access);
+}
+
+static inline void tzc_set_action(tzc_action_t action)
+{
+ tzc400_set_action(action);
+}
+
+
+static inline void tzc_enable_filters(void)
+{
+ tzc400_enable_filters();
+}
+
+static inline void tzc_disable_filters(void)
+{
+ tzc400_disable_filters();
+}
#endif /* __ASSEMBLY__ */
diff --git a/include/drivers/arm/tzc_common.h b/include/drivers/arm/tzc_common.h
new file mode 100644
index 0000000..9b73c3f
--- /dev/null
+++ b/include/drivers/arm/tzc_common.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#ifndef __TZC_COMMON_H__
+#define __TZC_COMMON_H__
+
+/*
+ * Offset of core registers from the start of the base of configuration
+ * registers for each region.
+ */
+
+/* ID Registers */
+#define PID0_OFF 0xfe0
+#define PID1_OFF 0xfe4
+#define PID2_OFF 0xfe8
+#define PID3_OFF 0xfec
+#define PID4_OFF 0xfd0
+#define CID0_OFF 0xff0
+#define CID1_OFF 0xff4
+#define CID2_OFF 0xff8
+#define CID3_OFF 0xffc
+
+/* Bit positions of TZC_ACTION registers */
+#define TZC_ACTION_RV_SHIFT 0
+#define TZC_ACTION_RV_MASK 0x3
+#define TZC_ACTION_RV_LOWOK 0x0
+#define TZC_ACTION_RV_LOWERR 0x1
+#define TZC_ACTION_RV_HIGHOK 0x2
+#define TZC_ACTION_RV_HIGHERR 0x3
+
+/* Used along with 'tzc_region_attributes_t' below */
+#define TZC_REGION_ATTR_S_RD_SHIFT 30
+#define TZC_REGION_ATTR_S_WR_SHIFT 31
+#define TZC_REGION_ATTR_F_EN_SHIFT 0
+#define TZC_REGION_ATTR_SEC_SHIFT 30
+#define TZC_REGION_ATTR_S_RD_MASK 0x1
+#define TZC_REGION_ATTR_S_WR_MASK 0x1
+#define TZC_REGION_ATTR_SEC_MASK 0x3
+
+#define TZC_REGION_ACCESS_WR_EN_SHIFT 16
+#define TZC_REGION_ACCESS_RD_EN_SHIFT 0
+#define TZC_REGION_ACCESS_ID_MASK 0xf
+
+/* Macros for allowing Non-Secure access to a region based on NSAID */
+#define TZC_REGION_ACCESS_RD(nsaid) \
+ ((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) << \
+ TZC_REGION_ACCESS_RD_EN_SHIFT)
+#define TZC_REGION_ACCESS_WR(nsaid) \
+ ((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) << \
+ TZC_REGION_ACCESS_WR_EN_SHIFT)
+#define TZC_REGION_ACCESS_RDWR(nsaid) \
+ (TZC_REGION_ACCESS_RD(nsaid) | \
+ TZC_REGION_ACCESS_WR(nsaid))
+
+#ifndef __ASSEMBLY__
+
+/* Returns offset of registers to program for a given region no */
+#define TZC_REGION_OFFSET(region_size, region_no) \
+ ((region_size) * (region_no))
+
+/*
+ * What type of action is expected when an access violation occurs.
+ * The memory requested is returned as zero. But we can also raise an event to
+ * let the system know it happened.
+ * We can raise an interrupt(INT) and/or cause an exception(ERR).
+ * TZC_ACTION_NONE - No interrupt, no Exception
+ * TZC_ACTION_ERR - No interrupt, raise exception -> sync external
+ * data abort
+ * TZC_ACTION_INT - Raise interrupt, no exception
+ * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
+ * external data abort
+ */
+typedef enum {
+ TZC_ACTION_NONE = 0,
+ TZC_ACTION_ERR = 1,
+ TZC_ACTION_INT = 2,
+ TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
+} tzc_action_t;
+
+/*
+ * Controls secure access to a region. If not enabled secure access is not
+ * allowed to region.
+ */
+typedef enum {
+ TZC_REGION_S_NONE = 0,
+ TZC_REGION_S_RD = 1,
+ TZC_REGION_S_WR = 2,
+ TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
+} tzc_region_attributes_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __TZC_COMMON_H__ */
diff --git a/include/drivers/arm/tzc_dmc500.h b/include/drivers/arm/tzc_dmc500.h
new file mode 100644
index 0000000..70f8ad2
--- /dev/null
+++ b/include/drivers/arm/tzc_dmc500.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#ifndef __TZC_DMC500_H__
+#define __TZC_DMC500_H__
+
+#include <tzc_common.h>
+
+#define SI_STATUS_OFFSET 0x000
+#define SI_STATE_CTRL_OFFSET 0x030
+#define SI_FLUSH_CTRL_OFFSET 0x034
+#define SI_INT_CONTROL_OFFSET 0x048
+
+#define SI_INT_STATUS_OFFSET 0x004
+#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET 0x008
+#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET 0x00c
+#define SI_FAIL_CONTROL_OFFSET 0x010
+#define SI_FAIL_ID_OFFSET 0x014
+#define SI_INT_CLR_OFFSET 0x04c
+
+/*
+ * DMC-500 has 2 system interfaces each having a similar set of regs
+ * to configure each interface.
+ */
+#define SI0_BASE 0x0000
+#define SI1_BASE 0x0200
+
+/* Bit positions of SIx_SI_STATUS */
+#define SI_EMPTY_SHIFT 0x01
+#define SI_STALL_ACK_SHIFT 0x00
+#define SI_EMPTY_MASK 0x01
+#define SI_STALL_ACK_MASK 0x01
+
+/* Bit positions of SIx_SI_INT_STATUS */
+#define PMU_REQ_INT_OVERFLOW_STATUS_SHIFT 18
+#define FAILED_ACCESS_INT_OVERFLOW_STATUS_SHIFT 16
+#define PMU_REQ_INT_STATUS_SHIFT 2
+#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_SHIFT 1
+#define FAILED_ACCESS_INT_STATUS_SHIFT 0
+#define PMU_REQ_INT_OVERFLOW_STATUS_MASK 0x1
+#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK 0x1
+#define PMU_REQ_INT_STATUS_MASK 0x1
+#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK 0x1
+#define FAILED_ACCESS_INT_STATUS_MASK 0x1
+
+/* Bit positions of SIx_TZ_FAIL_CONTROL */
+#define DIRECTION_SHIFT 24
+#define NON_SECURE_SHIFT 21
+#define PRIVILEGED_SHIFT 20
+#define FAILED_ACCESS_INT_INFO_RANK_MASKED_SHIFT 3
+#define FAILED_ACCESS_INT_INFO_UNMAPPED_SHIFT 2
+#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT 0x1
+#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_SHIFT 0
+#define DIRECTION_MASK 0x1
+#define NON_SECURE_MASK 0x1
+#define PRIVILEGED_MASK 0x1
+#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK 0x1
+#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK 0x1
+#define FAILED_ACCESS_INT_TZ_FAIL_MASK 1
+#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK 0x1
+
+/* Bit positions of SIx_FAIL_STATUS */
+#define FAIL_ID_VNET_SHIFT 24
+#define FAIL_ID_ID_SHIFT 0
+#define FAIL_ID_VNET_MASK 0xf
+#define FAIL_ID_ID_MASK 0xffffff
+
+/* Bit positions of SIx_SI_STATE_CONTRL */
+#define SI_STALL_REQ_GO 0x0
+#define SI_STALL_REQ_STALL 0x1
+
+/* Bit positions of SIx_SI_FLUSH_CONTROL */
+#define SI_FLUSH_REQ_INACTIVE 0x0
+#define SI_FLUSH_REQ_ACTIVE 0x1
+#define SI_FLUSH_REQ_MASK 0x1
+
+/* Bit positions of SIx_SI_INT_CONTROL */
+#define PMU_REQ_INT_EN_SHIFT 2
+#define OVERLAP_DETECT_INT_EN_SHIFT 1
+#define FAILED_ACCESS_INT_EN_SHIFT 0
+#define PMU_REQ_INT_EN_MASK 0x1
+#define OVERLAP_DETECT_INT_EN_MASK 0x1
+#define FAILED_ACCESS_INT_EN_MASK 0x1
+#define PMU_REQ_INT_EN 0x1
+#define OVERLAP_DETECT_INT_EN 0x1
+#define FAILED_ACCESS_INT_EN 0x1
+
+/* Bit positions of SIx_SI_INT_CLR */
+#define PMU_REQ_OFLOW_CLR_SHIFT 18
+#define FAILED_ACCESS_OFLOW_CLR_SHIFT 16
+#define PMU_REQ_INT_CLR_SHIFT 2
+#define FAILED_ACCESS_INT_CLR_SHIFT 0
+#define PMU_REQ_OFLOW_CLR_MASK 0x1
+#define FAILED_ACCESS_OFLOW_CLR_MASK 0x1
+#define PMU_REQ_INT_CLR_MASK 0x1
+#define FAILED_ACCESS_INT_CLR_MASK 0x1
+#define PMU_REQ_OFLOW_CLR 0x1
+#define FAILED_ACCESS_OFLOW_CLR 0x1
+#define PMU_REQ_INT_CLR 0x1
+#define FAILED_ACCESS_INT_CLR 0x1
+
+/* Macro to get the correct base register for a system interface */
+#define IFACE_OFFSET(sys_if) ((sys_if) ? SI1_BASE : SI0_BASE)
+
+#define MAX_SYS_IF_COUNT 2
+#define MAX_REGION_VAL 8
+
+/* DMC-500 supports striping across a max of 4 DMC instances */
+#define MAX_DMC_COUNT 4
+
+/* Consist of part_number_1 and part_number_0 */
+#define DMC500_PERIPHERAL_ID 0x0450
+
+/* Filter enable bits in a TZC */
+#define TZC_DMC500_REGION_ATTR_F_EN_MASK 0x1
+
+/* Length of registers for configuring each region */
+#define TZC_DMC500_REGION_SIZE 0x018
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+/*
+ * Contains the base addresses of all the DMC instances.
+ */
+typedef struct tzc_dmc500_driver_data {
+ uintptr_t dmc_base[MAX_DMC_COUNT];
+ int dmc_count;
+} tzc_dmc500_driver_data_t;
+
+void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data);
+void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions);
+void tzc_dmc500_configure_region(int region_no,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions);
+void tzc_dmc500_set_action(tzc_action_t action);
+void tzc_dmc500_config_complete(void);
+int tzc_dmc500_verify_complete(void);
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* __TZC_DMC500_H__ */
+
diff --git a/include/drivers/auth/auth_common.h b/include/drivers/auth/auth_common.h
index 52a895e..456f69f 100644
--- a/include/drivers/auth/auth_common.h
+++ b/include/drivers/auth/auth_common.h
@@ -46,6 +46,7 @@
AUTH_PARAM_SIG_ALG, /* The image signature algorithm */
AUTH_PARAM_HASH, /* A hash (including the algorithm) */
AUTH_PARAM_PUB_KEY, /* A public key */
+ AUTH_PARAM_NV_CTR, /* A non-volatile counter */
} auth_param_type_t;
/*
@@ -80,6 +81,7 @@
AUTH_METHOD_NONE = 0,
AUTH_METHOD_HASH, /* Authenticate by hash matching */
AUTH_METHOD_SIG, /* Authenticate by PK operation */
+ AUTH_METHOD_NV_CTR, /* Authenticate by Non-Volatile Counter */
AUTH_METHOD_NUM /* Number of methods */
} auth_method_type_t;
@@ -105,7 +107,8 @@
* Parameters for authentication by NV counter
*/
typedef struct auth_method_param_nv_ctr_s {
- auth_param_type_desc_t *nv_ctr; /* NV counter value */
+ auth_param_type_desc_t *cert_nv_ctr; /* NV counter in certificate */
+ auth_param_type_desc_t *plat_nv_ctr; /* NV counter in platform */
} auth_method_param_nv_ctr_t;
/*
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 6118c6e..f9f0715 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -113,15 +113,6 @@
}
/*******************************************************************************
- * Aarch64 translation tables manipulation helper prototypes
-******************************************************************************/
-uint64_t create_table_desc(uint64_t *next_table_ptr);
-uint64_t create_block_desc(uint64_t desc, uint64_t addr, uint32_t level);
-uint64_t create_device_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-uint64_t create_romem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-uint64_t create_rwmem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-
-/*******************************************************************************
* TLB maintenance accessor prototypes
******************************************************************************/
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index e9eebaa..2fe0a69 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -130,7 +130,9 @@
void arm_io_setup(void);
/* Security utility functions */
-void arm_tzc_setup(void);
+void arm_tzc400_setup(void);
+struct tzc_dmc500_driver_data;
+void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data);
/* Systimer utility function */
void arm_configure_sys_timer(void);
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index f92126b..636daf2 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -143,7 +143,7 @@
#define PLAT_ARM_NS_IMAGE_OFFSET 0xE0000000
/* TZC related constants */
-#define PLAT_ARM_TZC_FILTERS REG_ATTR_FILTER_BIT_ALL
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL
/* Trusted mailbox base address common to all CSS */
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
diff --git a/include/plat/arm/soc/common/soc_css_def.h b/include/plat/arm/soc/common/soc_css_def.h
index 428df4d..f1396a6 100644
--- a/include/plat/arm/soc/common/soc_css_def.h
+++ b/include/plat/arm/soc/common/soc_css_def.h
@@ -65,6 +65,13 @@
*/
#define SOC_CSS_NIC400_APB4_BRIDGE 4
+/* Non-volatile counters */
+#define SOC_TRUSTED_NVCTR_BASE 0x7fe70000
+#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE 4
+#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE 4
+
/* Keys */
#define SOC_KEYS_BASE 0x7fe80000
#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000)
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 5c61f38..5857501 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -60,7 +60,7 @@
int plat_get_image_source(unsigned int image_id,
uintptr_t *dev_handle,
uintptr_t *image_spec);
-unsigned long plat_get_ns_image_entrypoint(void);
+uintptr_t plat_get_ns_image_entrypoint(void);
unsigned int plat_my_core_pos(void);
int plat_core_pos_by_mpidr(u_register_t mpidr);
@@ -249,6 +249,8 @@
******************************************************************************/
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
unsigned int *flags);
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr);
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr);
#if ENABLE_PLAT_COMPAT
/*
diff --git a/lib/aarch64/xlat_helpers.c b/lib/aarch64/xlat_helpers.c
deleted file mode 100644
index d401ffc..0000000
--- a/lib/aarch64/xlat_helpers.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2013-2014, 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 <arch.h>
-#include <assert.h>
-
-/*******************************************************************************
- * Helper to create a level 1/2 table descriptor which points to a level 2/3
- * table.
- ******************************************************************************/
-unsigned long create_table_desc(unsigned long *next_table_ptr)
-{
- unsigned long desc = (unsigned long) next_table_ptr;
-
- /* Clear the last 12 bits */
- desc >>= FOUR_KB_SHIFT;
- desc <<= FOUR_KB_SHIFT;
-
- desc |= TABLE_DESC;
-
- return desc;
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to addr
- ******************************************************************************/
-unsigned long create_block_desc(unsigned long desc,
- unsigned long addr,
- unsigned int level)
-{
- switch (level) {
- case LEVEL1:
- desc |= (addr << FIRST_LEVEL_DESC_N) | BLOCK_DESC;
- break;
- case LEVEL2:
- desc |= (addr << SECOND_LEVEL_DESC_N) | BLOCK_DESC;
- break;
- case LEVEL3:
- desc |= (addr << THIRD_LEVEL_DESC_N) | TABLE_DESC;
- break;
- default:
- assert(0);
- }
-
- return desc;
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with Device nGnRE attributes.
- ******************************************************************************/
-unsigned long create_device_block(unsigned long output_addr,
- unsigned int level,
- unsigned int ns)
-{
- unsigned long upper_attrs, lower_attrs, desc;
-
- lower_attrs = LOWER_ATTRS(ACCESS_FLAG | OSH | AP_RW);
- lower_attrs |= LOWER_ATTRS(ns | ATTR_DEVICE_INDEX);
- upper_attrs = UPPER_ATTRS(XN);
- desc = upper_attrs | lower_attrs;
-
- return create_block_desc(desc, output_addr, level);
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with inner-shareable normal wbwa read-only memory attributes.
- ******************************************************************************/
-unsigned long create_romem_block(unsigned long output_addr,
- unsigned int level,
- unsigned int ns)
-{
- unsigned long upper_attrs, lower_attrs, desc;
-
- lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RO);
- lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
- upper_attrs = UPPER_ATTRS(0ull);
- desc = upper_attrs | lower_attrs;
-
- return create_block_desc(desc, output_addr, level);
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with inner-shareable normal wbwa read-write memory attributes.
- ******************************************************************************/
-unsigned long create_rwmem_block(unsigned long output_addr,
- unsigned int level,
- unsigned int ns)
-{
- unsigned long upper_attrs, lower_attrs, desc;
-
- lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RW);
- lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
- upper_attrs = UPPER_ATTRS(XN);
- desc = upper_attrs | lower_attrs;
-
- return create_block_desc(desc, output_addr, level);
-}
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index e934d72..71d9747 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -58,6 +58,14 @@
TRUSTED_KEY_CERT := ${BUILD_PLAT}/trusted_key.crt
FWU_CERT := ${BUILD_PLAT}/fwu_cert.crt
+# Default non-volatile counter values (overridable by the platform)
+TFW_NVCTR_VAL ?= 0
+NTFW_NVCTR_VAL ?= 0
+
+# Pass the non-volatile counters to the cert_create tool
+$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr))
+$(eval $(call CERT_ADD_CMD_OPT,${NTFW_NVCTR_VAL},--ntfw-nvctr))
+
# Add Trusted Key certificate to the fip_create and cert_create command line options
$(eval $(call FIP_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert))
$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_KEY_CERT},--trusted-key-cert))
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index 103aafb..7ae00cc 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -31,11 +31,14 @@
#include <arm_def.h>
#include <assert.h>
#include <platform.h>
+#include <platform_oid.h>
#include <stdint.h>
#include <string.h>
/* Weak definition may be overridden in specific platform */
#pragma weak plat_match_rotpk
+#pragma weak plat_get_nv_ctr
+#pragma weak plat_set_nv_ctr
/* SHA256 algorithm */
#define SHA256_BYTES 32
@@ -148,3 +151,43 @@
return 0;
}
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ const char *oid;
+ uint32_t *nv_ctr_addr;
+
+ assert(cookie != NULL);
+ assert(nv_ctr != NULL);
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = (uint32_t *)TFW_NVCTR_BASE;
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = (uint32_t *)NTFW_CTR_BASE;
+ } else {
+ return 1;
+ }
+
+ *nv_ctr = (unsigned int)(*nv_ctr_addr);
+
+ return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. On Juno and FVP, the non-volatile
+ * counters are RO and cannot be modified. We expect the values in the
+ * certificates to always match the RO values so that this function is never
+ * called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index da6beec..6ddc0c9 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -51,6 +51,11 @@
endif
$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+ # Certificate NV-Counters. Use values corresponding to tied off values in
+ # ARM development platforms
+ TFW_NVCTR_VAL ?= 31
+ NTFW_NVCTR_VAL ?= 223
+
BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c
BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c
endif
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index dbca280..b0f07ef 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -69,7 +69,13 @@
#define PCIE_EXP_BASE 0x40000000
#define TZRNG_BASE 0x7fe60000
-#define TZNVCTR_BASE 0x7fe70000
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE 0x7fe70000
+#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE 4
+#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE 4
/* Keys */
#define SOC_KEYS_BASE 0x7fe80000
diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c
index 0cf8450..b1de977 100644
--- a/plat/arm/board/fvp/fvp_security.c
+++ b/plat/arm/board/fvp/fvp_security.c
@@ -46,5 +46,5 @@
*/
if (get_arm_config()->flags & ARM_CONFIG_HAS_TZC)
- arm_tzc_setup();
+ arm_tzc400_setup();
}
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 3428cb5..ca8e35e 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -113,7 +113,7 @@
* would normally use the default ID so allow that too.
*/
#define PLAT_ARM_TZC_BASE 0x2a4a0000
-#define PLAT_ARM_TZC_FILTERS REG_ATTR_FILTER_BIT(0)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | \
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index aad2e2e..afd939d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -65,7 +65,7 @@
FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
plat/arm/common/arm_cci.c
-FVP_SECURITY_SOURCES := drivers/arm/tzc400/tzc400.c \
+FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
plat/arm/board/fvp/fvp_security.c \
plat/arm/common/arm_tzc400.c
diff --git a/plat/arm/board/juno/juno_security.c b/plat/arm/board/juno/juno_security.c
index f9386ca..202342a 100644
--- a/plat/arm/board/juno/juno_security.c
+++ b/plat/arm/board/juno/juno_security.c
@@ -65,7 +65,7 @@
void plat_arm_security_setup(void)
{
/* Initialize the TrustZone Controller */
- arm_tzc_setup();
+ arm_tzc400_setup();
/* Do ARM CSS internal NIC setup */
css_init_nic400();
/* Do ARM CSS SoC security setup */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 0a2244d..4fda4ca 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -37,7 +37,7 @@
JUNO_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
plat/arm/common/arm_cci.c
-JUNO_SECURITY_SOURCES := drivers/arm/tzc400/tzc400.c \
+JUNO_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
plat/arm/board/juno/juno_security.c \
plat/arm/common/arm_tzc400.c
diff --git a/plat/arm/common/aarch64/arm_common.c b/plat/arm/common/aarch64/arm_common.c
index c84a65b..19a4931 100644
--- a/plat/arm/common/aarch64/arm_common.c
+++ b/plat/arm/common/aarch64/arm_common.c
@@ -93,7 +93,7 @@
DEFINE_CONFIGURE_MMU_EL(3)
-unsigned long plat_get_ns_image_entrypoint(void)
+uintptr_t plat_get_ns_image_entrypoint(void)
{
return PLAT_ARM_NS_IMAGE_OFFSET;
}
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 8b46aae..3962940 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -48,53 +48,53 @@
* When booting an EL3 payload, this is simplified: we configure region 0 with
* secure access only and do not enable any other region.
******************************************************************************/
-void arm_tzc_setup(void)
+void arm_tzc400_setup(void)
{
INFO("Configuring TrustZone Controller\n");
- tzc_init(PLAT_ARM_TZC_BASE);
+ tzc400_init(PLAT_ARM_TZC_BASE);
/* Disable filters. */
- tzc_disable_filters();
+ tzc400_disable_filters();
#ifndef EL3_PAYLOAD_BASE
/* Region 0 set to no access by default */
- tzc_configure_region0(TZC_REGION_S_NONE, 0);
+ tzc400_configure_region0(TZC_REGION_S_NONE, 0);
/* Region 1 set to cover Secure part of DRAM */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 1,
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 1,
ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END,
TZC_REGION_S_RDWR,
0);
/* Region 2 set to cover Non-Secure access to 1st DRAM address range.
* Apply the same configuration to given filters in the TZC. */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 2,
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 2,
ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
/* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 3,
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 3,
ARM_DRAM2_BASE, ARM_DRAM2_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
#else
/* Allow secure access only to DRAM for EL3 payloads. */
- tzc_configure_region0(TZC_REGION_S_RDWR, 0);
+ tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
#endif /* EL3_PAYLOAD_BASE */
/*
* Raise an exception if a NS device tries to access secure memory
* TODO: Add interrupt handling support.
*/
- tzc_set_action(TZC_ACTION_ERR);
+ tzc400_set_action(TZC_ACTION_ERR);
/* Enable filters. */
- tzc_enable_filters();
+ tzc400_enable_filters();
}
void plat_arm_security_setup(void)
{
- arm_tzc_setup();
+ arm_tzc400_setup();
}
diff --git a/plat/arm/common/arm_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c
new file mode 100644
index 0000000..f0ed9a6
--- /dev/null
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, 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 <arm_def.h>
+#include <assert.h>
+#include <debug.h>
+#include <platform_def.h>
+#include <tzc_dmc500.h>
+
+/*******************************************************************************
+ * Initialize the DMC500-TrustZone Controller for ARM standard platforms.
+ * Configure both the interfaces on Region 0 with no access, Region 1 with
+ * secure access only, and the remaining DRAM regions access from the
+ * given Non-Secure masters.
+ *
+ * When booting an EL3 payload, this is simplified: we configure region 0 with
+ * secure access only and do not enable any other region.
+ ******************************************************************************/
+void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data)
+{
+ assert(plat_driver_data);
+
+ INFO("Configuring DMC-500 TZ Settings\n");
+
+ tzc_dmc500_driver_init(plat_driver_data);
+
+#ifndef EL3_PAYLOAD_BASE
+ /* Region 0 set to no access by default */
+ tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0);
+
+ /* Region 1 set to cover Secure part of DRAM */
+ tzc_dmc500_configure_region(1, ARM_AP_TZC_DRAM1_BASE,
+ ARM_AP_TZC_DRAM1_END,
+ TZC_REGION_S_RDWR,
+ 0);
+
+ /* Region 2 set to cover Non-Secure access to 1st DRAM address range.*/
+ tzc_dmc500_configure_region(2,
+ ARM_NS_DRAM1_BASE,
+ ARM_NS_DRAM1_END,
+ TZC_REGION_S_NONE,
+ PLAT_ARM_TZC_NS_DEV_ACCESS);
+
+ /* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
+ tzc_dmc500_configure_region(3,
+ ARM_DRAM2_BASE,
+ ARM_DRAM2_END,
+ TZC_REGION_S_NONE,
+ PLAT_ARM_TZC_NS_DEV_ACCESS);
+#else
+ /* Allow secure access only to DRAM for EL3 payloads */
+ tzc_dmc500_configure_region0(TZC_REGION_S_RDWR, 0);
+#endif
+ /*
+ * Raise an exception if a NS device tries to access secure memory
+ * TODO: Add interrupt handling support.
+ */
+ tzc_dmc500_set_action(TZC_ACTION_RV_LOWERR);
+
+ /*
+ * Flush the configuration settings to have an affect. Validate
+ * flush by checking FILTER_EN is set on region 1 attributes
+ * register.
+ */
+ tzc_dmc500_config_complete();
+
+ /*
+ * Wait for the flush to complete.
+ * TODO: Have a timeout for this loop
+ */
+ while (tzc_dmc500_verify_complete())
+ ;
+}
diff --git a/plat/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c
index 8783775..749009e 100644
--- a/plat/mediatek/mt8173/bl31_plat_setup.c
+++ b/plat/mediatek/mt8173/bl31_plat_setup.c
@@ -50,13 +50,15 @@
unsigned long __COHERENT_RAM_END__;
/*
- * The next 2 constants identify the extents of the code & RO data region.
- * These addresses are used by the MMU setup code and therefore they must be
- * page-aligned. It is the responsibility of the linker script to ensure that
- * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ * The next 3 constants identify the extents of the code, RO data region and the
+ * limit of the BL31 image. These addresses are used by the MMU setup code and
+ * therefore they must be page-aligned. It is the responsibility of the linker
+ * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols
+ * refer to page-aligned addresses.
*/
#define BL31_RO_BASE (unsigned long)(&__RO_START__)
#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL31_END (unsigned long)(&__BL31_END__)
/*
* The next 2 constants identify the extents of the coherent memory region.
@@ -108,6 +110,13 @@
MCU_BUS_DCM_EN);
}
+static void platform_setup_sram(void)
+{
+ /* protect BL31 memory from non-secure read/write access */
+ mmio_write_32(SRAMROM_SEC_ADDR, (uint32_t)(BL31_END + 0x3ff) & 0x3fc00);
+ mmio_write_32(SRAMROM_SEC_CTRL, 0x10000ff9);
+}
+
/*******************************************************************************
* Return a pointer to the 'entry_point_info' structure of the next image for
* the security state specified. BL33 corresponds to the non-secure image type
@@ -156,6 +165,7 @@
void bl31_platform_setup(void)
{
platform_setup_cpu();
+ platform_setup_sram();
plat_delay_timer_init();
diff --git a/plat/mediatek/mt8173/drivers/spm/spm.c b/plat/mediatek/mt8173/drivers/spm/spm.c
index 45defd8..f28b264 100644
--- a/plat/mediatek/mt8173/drivers/spm/spm.c
+++ b/plat/mediatek/mt8173/drivers/spm/spm.c
@@ -384,6 +384,10 @@
void spm_boot_init(void)
{
+ /* set spm transaction to secure mode */
+ mmio_write_32(DEVAPC0_APC_CON, 0x0);
+ mmio_write_32(DEVAPC0_MAS_SEC_0, 0x200);
+
/* Only CPU0 is online during boot, initialize cpu online reserve bit */
mmio_write_32(SPM_PCM_RESERVE, 0xFE);
mmio_clrbits_32(AP_PLL_CON3, 0xFFFFF);
diff --git a/plat/mediatek/mt8173/include/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h
index 39bab14..0113d60 100644
--- a/plat/mediatek/mt8173/include/mt8173_def.h
+++ b/plat/mediatek/mt8173/include/mt8173_def.h
@@ -40,11 +40,13 @@
/* Register base address */
#define IO_PHYS (0x10000000)
#define INFRACFG_AO_BASE (IO_PHYS + 0x1000)
+#define SRAMROM_SEC_BASE (IO_PHYS + 0x1800)
#define PERI_CON_BASE (IO_PHYS + 0x3000)
#define GPIO_BASE (IO_PHYS + 0x5000)
#define SPM_BASE (IO_PHYS + 0x6000)
#define RGU_BASE (IO_PHYS + 0x7000)
#define PMIC_WRAP_BASE (IO_PHYS + 0xD000)
+#define DEVAPC0_BASE (IO_PHYS + 0xE000)
#define MCUCFG_BASE (IO_PHYS + 0x200000)
#define APMIXED_BASE (IO_PHYS + 0x209000)
#define TRNG_BASE (IO_PHYS + 0x20F000)
@@ -57,6 +59,14 @@
#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000)
#define MTK_DEV_RNG1_SIZE 0x4000000
+/* SRAMROM related registers */
+#define SRAMROM_SEC_CTRL (SRAMROM_SEC_BASE + 0x4)
+#define SRAMROM_SEC_ADDR (SRAMROM_SEC_BASE + 0x8)
+
+/* DEVAPC0 related registers */
+#define DEVAPC0_MAS_SEC_0 (DEVAPC0_BASE + 0x500)
+#define DEVAPC0_APC_CON (DEVAPC0_BASE + 0xF00)
+
/*******************************************************************************
* UART related constants
******************************************************************************/
diff --git a/plat/rockchip/common/aarch64/plat_helpers.S b/plat/rockchip/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..a90dcd7
--- /dev/null
+++ b/plat/rockchip/common/aarch64/plat_helpers.S
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2013-2016, 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 <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a53.h>
+#include <cortex_a72.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+ .globl cpuson_entry_point
+ .globl cpuson_flags
+ .globl platform_cpu_warmboot
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_report_exception
+ .globl platform_is_primary_cpu
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+
+
+#define RK_REVISION(rev) RK_PLAT_CFG##rev
+#define RK_HANDLER(rev) plat_reset_handler_juno_r##rev
+#define JUMP_TO_HANDLER_IF_RK_R(revision) \
+ jump_to_handler RK_REVISION(revision), RK_HANDLER(revision)
+
+ /*
+ * Helper macro to jump to the given handler if the board revision
+ * matches.
+ * Expects the Juno board revision in x0.
+ *
+ */
+ .macro jump_to_handler _revision, _handler
+ cmp x0, #\_revision
+ b.eq \_handler
+ .endm
+
+ /*
+ * Helper macro that reads the part number of the current CPU and jumps
+ * to the given label if it matches the CPU MIDR provided.
+ */
+ .macro jump_if_cpu_midr _cpu_midr, _label
+ mrs x0, midr_el1
+ ubfx x0, x0, MIDR_PN_SHIFT, #12
+ cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+ b.eq \_label
+ .endm
+
+ /*
+ * Platform reset handler for rockchip.
+ * only A53 cores
+ */
+func RK_HANDLER(0)
+ ret
+endfunc RK_HANDLER(0)
+
+ /*
+ * Platform reset handler for rockchip.
+ * - Cortex-A53 processor cluster;
+ * - Cortex-A72 processor cluster.
+ *
+ * This handler does the following:
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72
+ * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72
+ */
+func RK_HANDLER(1)
+ /*
+ * Nothing to do on Cortex-A53.
+ *
+ */
+ jump_if_cpu_midr CORTEX_A72_MIDR, A72
+ ret
+
+A72:
+ /* Cortex-A72 specific settings */
+ mov x0, #((2 << L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (0x1 << 5))
+ msr L2CTLR_EL1, x0
+ isb
+ ret
+endfunc RK_HANDLER(1)
+
+ /*
+ * void plat_reset_handler(void);
+ *
+ * Determine the SOC type and call the appropriate reset
+ * handler.
+ *
+ */
+func plat_reset_handler
+
+ mov x0, RK_PLAT_AARCH_CFG
+
+ JUMP_TO_HANDLER_IF_RK_R(0)
+ JUMP_TO_HANDLER_IF_RK_R(1)
+
+ /* SOC type is not supported */
+not_supported:
+ b not_supported
+endfunc plat_reset_handler
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* rk3368 does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+func platform_is_primary_cpu
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_RK_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc platform_is_primary_cpu
+
+ /* --------------------------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * --------------------------------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_RK_UART_BASE
+ mov_imm x1, PLAT_RK_UART_CLOCK
+ mov_imm x2, PLAT_RK_UART_BAUDRATE
+ b console_core_init
+endfunc plat_crash_console_init
+
+ /* --------------------------------------------------------------------
+ * int plat_crash_console_putc(void)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * --------------------------------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_RK_UART_BASE
+ b console_core_putc
+endfunc plat_crash_console_putc
+
+ /* --------------------------------------------------------------------
+ * void platform_cpu_warmboot (void);
+ * cpus online or resume enterpoint
+ * --------------------------------------------------------------------
+ */
+func platform_cpu_warmboot
+ mrs x0, MPIDR_EL1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ /* --------------------------------------------------------------------
+ * big cluster id is 1
+ * big cores id is from 0-3, little cores id 4-7
+ * --------------------------------------------------------------------
+ */
+ add x0, x1, x0, lsr #6
+ /* --------------------------------------------------------------------
+ * get per cpuup flag
+ * --------------------------------------------------------------------
+ */
+ adr x4, cpuson_flags
+ add x4, x4, x0, lsl #2
+ ldr w1, [x4]
+ /* --------------------------------------------------------------------
+ * get per cpuup boot addr
+ * --------------------------------------------------------------------
+ */
+ adr x5, cpuson_entry_point
+ ldr x2, [x5, x0, lsl #3]
+ /* --------------------------------------------------------------------
+ * check cpuon reason
+ * --------------------------------------------------------------------
+ */
+ ldr w3, =PMU_CPU_AUTO_PWRDN
+ cmp w1, w3
+ b.eq boot_entry
+ ldr w3, =PMU_CPU_HOTPLUG
+ cmp w1, w3
+ b.eq boot_entry
+ /* --------------------------------------------------------------------
+ * If the boot core cpuson_flags or cpuson_entry_point is not
+ * expection. force the core into wfe.
+ * --------------------------------------------------------------------
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+boot_entry:
+ mov w0, #0
+ str w0, [x4]
+ br x2
+endfunc platform_cpu_warmboot
+
+ /* --------------------------------------------------------------------
+ * Per-CPU Secure entry point - resume or power up
+ * --------------------------------------------------------------------
+ */
+ .section tzfw_coherent_mem, "a"
+ .align 3
+cpuson_entry_point:
+ .rept PLATFORM_CORE_COUNT
+ .quad 0
+ .endr
+cpuson_flags:
+ .rept PLATFORM_CORE_COUNT
+ .quad 0
+ .endr
diff --git a/plat/rockchip/common/aarch64/platform_common.c b/plat/rockchip/common/aarch64/platform_common.c
new file mode 100644
index 0000000..3f912a4
--- /dev/null
+++ b/plat/rockchip/common/aarch64/platform_common.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013-2016, 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 <arch_helpers.h>
+#include <arm_gic.h>
+#include <bl_common.h>
+#include <cci.h>
+#include <debug.h>
+#include <string.h>
+#include <xlat_tables.h>
+#include <platform_def.h>
+#include <plat_private.h>
+
+#ifdef PLAT_RK_CCI_BASE
+static const int cci_map[] = {
+ PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX
+};
+#endif
+
+/******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void plat_configure_mmu_el ## _el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(plat_rk_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el ## _el(0); \
+ }
+
+/* Define EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(3)
+
+uint64_t plat_get_syscnt_freq(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+void plat_cci_init(void)
+{
+#ifdef PLAT_RK_CCI_BASE
+ /* Initialize CCI driver */
+ cci_init(PLAT_RK_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+#endif
+}
+
+void plat_cci_enable(void)
+{
+ /*
+ * Enable CCI coherency for this cluster.
+ * No need for locks as no other cpu is active at the moment.
+ */
+#ifdef PLAT_RK_CCI_BASE
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+#endif
+}
+
+void plat_cci_disable(void)
+{
+#ifdef PLAT_RK_CCI_BASE
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+#endif
+}
diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c
new file mode 100644
index 0000000..30fb5ac
--- /dev/null
+++ b/plat/rockchip/common/bl31_plat_setup.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016, 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 <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+unsigned long __RO_START__;
+unsigned long __RO_END__;
+
+unsigned long __COHERENT_RAM_START__;
+unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+ void *plat_params_from_bl2)
+{
+ console_init(PLAT_RK_UART_BASE, PLAT_RK_UART_CLOCK,
+ PLAT_RK_UART_BAUDRATE);
+
+ VERBOSE("bl31_setup\n");
+
+ /* Passing a NULL context is a critical programming error */
+ assert(from_bl2);
+
+ assert(from_bl2->h.type == PARAM_BL31);
+ assert(from_bl2->h.version >= VERSION_1);
+
+ bl32_ep_info = *from_bl2->bl32_ep_info;
+ bl33_ep_info = *from_bl2->bl33_ep_info;
+
+ /*
+ * The code for resuming cpu from suspend must be excuted in pmusram.
+ * Copy the code into pmusram.
+ */
+ plat_rockchip_pmusram_prepare();
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ plat_delay_timer_init();
+ plat_rockchip_soc_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_rockchip_gic_driver_init();
+ plat_rockchip_gic_init();
+ plat_rockchip_pmu_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_cci_init();
+ plat_cci_enable();
+ plat_configure_mmu_el3(BL31_RO_BASE,
+ (BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE),
+ BL31_RO_BASE,
+ BL31_RO_LIMIT,
+ BL31_COHERENT_RAM_BASE,
+ BL31_COHERENT_RAM_LIMIT);
+}
diff --git a/plat/rockchip/common/drivers/pmu/pmu_com.h b/plat/rockchip/common/drivers/pmu/pmu_com.h
new file mode 100644
index 0000000..0cab53c
--- /dev/null
+++ b/plat/rockchip/common/drivers/pmu/pmu_com.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+
+#ifndef __PMU_COM_H__
+#define __PMU_COM_H__
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+
+#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock)
+
+#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock)
+
+#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock)
+/*****************************************************************************
+ * power domain on or off
+ *****************************************************************************/
+enum pmu_pd_state {
+ pmu_pd_on = 0,
+ pmu_pd_off = 1
+};
+
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak pmu_power_domain_ctr
+#pragma weak check_cpu_wfie
+
+static inline uint32_t pmu_power_domain_st(uint32_t pd)
+{
+ uint32_t pwrdn_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd);
+
+ if (pwrdn_st)
+ return pmu_pd_off;
+ else
+ return pmu_pd_on;
+}
+
+static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
+{
+ uint32_t val;
+ uint32_t loop = 0;
+ int ret = 0;
+
+ rockchip_pd_lock_get();
+
+ val = mmio_read_32(PMU_BASE + PMU_PWRDN_CON);
+ if (pd_state == pmu_pd_off)
+ val |= BIT(pd);
+ else
+ val &= ~BIT(pd);
+
+ mmio_write_32(PMU_BASE + PMU_PWRDN_CON, val);
+ dsb();
+
+ while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if (pmu_power_domain_st(pd) != pd_state) {
+ WARN("%s: %d, %d, error!\n", __func__, pd, pd_state);
+ ret = -EINVAL;
+ }
+
+ rockchip_pd_lock_rls();
+
+ return ret;
+}
+
+static int check_cpu_wfie(uint32_t cpu_id, uint32_t wfie_msk)
+{
+ uint32_t cluster_id, loop = 0;
+
+ if (cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) {
+ cluster_id = 1;
+ cpu_id -= PLATFORM_CLUSTER0_CORE_COUNT;
+ } else {
+ cluster_id = 0;
+ }
+
+ if (cluster_id)
+ wfie_msk <<= (clstb_cpu_wfe + cpu_id);
+ else
+ wfie_msk <<= (clstl_cpu_wfe + cpu_id);
+
+ while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & wfie_msk) &&
+ (loop < CHK_CPU_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if ((mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & wfie_msk) == 0) {
+ WARN("%s: %d, %d, %d, error!\n", __func__,
+ cluster_id, cpu_id, wfie_msk);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#endif /* __PMU_COM_H__ */
diff --git a/plat/rockchip/common/include/plat_macros.S b/plat/rockchip/common/include/plat_macros.S
new file mode 100644
index 0000000..ce68cf1
--- /dev/null
+++ b/plat/rockchip/common/include/plat_macros.S
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014-2016, 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.
+ */
+#ifndef __ROCKCHIP_PLAT_MACROS_S__
+#define __ROCKCHIP_PLAT_MACROS_S__
+
+#include <cci.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include <gicv3.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+ .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+ /* ---------------------------------------------
+ * The below utility macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31 on ARM standard platforms.
+ * Expects: GICD base in x16, GICC base in x17
+ * Clobbers: x0 - x10, sp
+ * ---------------------------------------------
+ */
+ .macro plat_print_gic_regs
+
+ mov_imm x16, PLAT_RK_GICD_BASE
+ mov_imm x17, PLAT_RK_GICC_BASE
+
+ /* Check for GICv3 system register access */
+ mrs x7, id_aa64pfr0_el1
+ ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x7, #1
+ b.ne print_gicv2
+
+ /* Check for SRE enable */
+ mrs x8, ICC_SRE_EL3
+ tst x8, #ICC_SRE_SRE_BIT
+ b.eq print_gicv2
+
+ /* Load the icc reg list to x6 */
+ adr x6, icc_regs
+ /* Load the icc regs to gp regs used by str_in_crash_buf_print */
+ mrs x8, ICC_HPPIR0_EL1
+ mrs x9, ICC_HPPIR1_EL1
+ mrs x10, ICC_CTLR_EL3
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ b print_gic_common
+
+print_gicv2:
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+print_gic_common:
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+ .endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ------------------------------------------------
+ * The below macro prints out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1.
+ * Clobbers: x0 - x9, sp
+ * ------------------------------------------------
+ */
+ .macro plat_print_interconnect_regs
+#if PLATFORM_CLUSTER_COUNT > 1
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+#endif
+ .endm
+
+#endif /* __ROCKCHIP_PLAT_MACROS_S__ */
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
new file mode 100644
index 0000000..67fb827
--- /dev/null
+++ b/plat/rockchip/common/include/plat_private.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2014-2016, 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.
+ */
+
+#ifndef __PLAT_PRIVATE_H__
+#define __PLAT_PRIVATE_H__
+
+#ifndef __ASSEMBLY__
+#include <mmio.h>
+#include <stdint.h>
+#include <xlat_tables.h>
+
+/******************************************************************************
+ * For rockchip socs pm ops
+ ******************************************************************************/
+struct rockchip_pm_ops_cb {
+ int (*cores_pwr_dm_on)(unsigned long mpidr, uint64_t entrypoint);
+ int (*cores_pwr_dm_off)(void);
+ int (*cores_pwr_dm_on_finish)(void);
+ int (*cores_pwr_dm_suspend)(void);
+ int (*cores_pwr_dm_resume)(void);
+ int (*sys_pwr_dm_suspend)(void);
+ int (*sys_pwr_dm_resume)(void);
+ void (*sys_gbl_soft_reset)(void) __dead2;
+ void (*system_off)(void) __dead2;
+};
+
+/******************************************************************************
+ * The register have write-mask bits, it is mean, if you want to set the bits,
+ * you needs set the write-mask bits at the same time,
+ * The write-mask bits is in high 16-bits.
+ * The fllowing macro definition helps access write-mask bits reg efficient!
+ ******************************************************************************/
+#define REG_MSK_SHIFT 16
+
+#ifndef BIT
+#define BIT(nr) (1 << (nr))
+#endif
+
+#ifndef WMSK_BIT
+#define WMSK_BIT(nr) BIT((nr) + REG_MSK_SHIFT)
+#endif
+
+/* set one bit with write mask */
+#ifndef BIT_WITH_WMSK
+#define BIT_WITH_WMSK(nr) (BIT(nr) | WMSK_BIT(nr))
+#endif
+
+#ifndef BITS_SHIFT
+#define BITS_SHIFT(bits, shift) (bits << (shift))
+#endif
+
+#ifndef BITS_WITH_WMASK
+#define BITS_WITH_WMASK(msk, bits, shift)\
+ (BITS_SHIFT(bits, shift) | BITS_SHIFT(msk, (shift + REG_MSK_SHIFT)))
+#endif
+
+/******************************************************************************
+ * Function and variable prototypes
+ *****************************************************************************/
+void plat_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+
+void plat_cci_init(void);
+void plat_cci_enable(void);
+void plat_cci_disable(void);
+
+void plat_delay_timer_init(void);
+
+void plat_rockchip_gic_driver_init(void);
+void plat_rockchip_gic_init(void);
+void plat_rockchip_gic_cpuif_enable(void);
+void plat_rockchip_gic_cpuif_disable(void);
+void plat_rockchip_gic_pcpu_init(void);
+
+void plat_rockchip_pmusram_prepare(void);
+void plat_rockchip_pmu_init(void);
+void plat_rockchip_soc_init(void);
+void plat_setup_rockchip_pm_ops(struct rockchip_pm_ops_cb *ops);
+
+extern const unsigned char rockchip_power_domain_tree_desc[];
+
+extern void *pmu_cpuson_entrypoint_start;
+extern void *pmu_cpuson_entrypoint_end;
+extern uint64_t cpuson_entry_point[PLATFORM_CORE_COUNT];
+extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT];
+
+extern const mmap_region_t plat_rk_mmap[];
+#endif /* __ASSEMBLY__ */
+
+/* only Cortex-A53 */
+#define RK_PLAT_CFG0 0
+
+/* include Cortex-A72 */
+#define RK_PLAT_CFG1 1
+
+#endif /* __PLAT_PRIVATE_H__ */
diff --git a/plat/rockchip/common/plat_delay_timer.c b/plat/rockchip/common/plat_delay_timer.c
new file mode 100644
index 0000000..797ce05
--- /dev/null
+++ b/plat/rockchip/common/plat_delay_timer.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, 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 <arch_helpers.h>
+#include <delay_timer.h>
+#include <platform_def.h>
+
+static uint32_t plat_get_timer_value(void)
+{
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. We apply bitwise NOT operator to the tick values returned
+ * by read_cntpct_el0() to simulate the down counter.
+ */
+ return (uint32_t)(~read_cntpct_el0());
+}
+
+static const timer_ops_t plat_timer_ops = {
+ .get_timer_value = plat_get_timer_value,
+ .clk_mult = 1,
+ .clk_div = SYS_COUNTER_FREQ_IN_MHZ,
+};
+
+void plat_delay_timer_init(void)
+{
+ timer_init(&plat_timer_ops);
+}
diff --git a/plat/rockchip/common/plat_pm.c b/plat/rockchip/common/plat_pm.c
new file mode 100644
index 0000000..fcd47a8
--- /dev/null
+++ b/plat/rockchip/common/plat_pm.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2013-2016, 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 <arch_helpers.h>
+#include <assert.h>
+#include <console.h>
+#include <errno.h>
+#include <debug.h>
+#include <psci.h>
+#include <delay_timer.h>
+#include <platform_def.h>
+#include <plat_private.h>
+
+/* Macros to read the rk power domain state */
+#define RK_CORE_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define RK_CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define RK_SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+static uintptr_t rockchip_sec_entrypoint;
+
+static struct rockchip_pm_ops_cb *rockchip_ops;
+
+static void plat_rockchip_sys_pwr_domain_resume(void)
+{
+ plat_rockchip_gic_init();
+ if (rockchip_ops && rockchip_ops->sys_pwr_dm_resume)
+ rockchip_ops->sys_pwr_dm_resume();
+}
+
+static void plat_rockchip_cores_pwr_domain_resume(void)
+{
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_resume)
+ rockchip_ops->cores_pwr_dm_resume();
+
+ /* Enable the gic cpu interface */
+ plat_rockchip_gic_pcpu_init();
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_rockchip_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * Rockchip standard platform handler called to check the validity of the power
+ * state parameter.
+ ******************************************************************************/
+int rockchip_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's probably to enter standby only on power level 0
+ * ignore any other power level.
+ */
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] =
+ PLAT_MAX_RET_STATE;
+ } else {
+ for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ PLAT_MAX_OFF_STATE;
+ }
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+/*******************************************************************************
+ * RockChip handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+void rockchip_cpu_standby(plat_local_state_t cpu_state)
+{
+ unsigned int scr;
+
+ assert(cpu_state == PLAT_MAX_RET_STATE);
+
+ scr = read_scr_el3();
+ /* Enable PhysicalIRQ bit for NS world to wake the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT);
+ isb();
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR to the original value, synchronisation of scr_el3 is
+ * done by eret while el3_exit to save some execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+int rockchip_pwr_domain_on(u_register_t mpidr)
+{
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_on)
+ rockchip_ops->cores_pwr_dm_on(mpidr, rockchip_sec_entrypoint);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void rockchip_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ plat_rockchip_gic_cpuif_disable();
+
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_cci_disable();
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_off)
+ rockchip_ops->cores_pwr_dm_off();
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ if (RK_CORE_PWR_STATE(target_state) == PLAT_MAX_RET_STATE)
+ return;
+
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ if (rockchip_ops && rockchip_ops->sys_pwr_dm_suspend)
+ rockchip_ops->sys_pwr_dm_suspend();
+ } else {
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_suspend)
+ rockchip_ops->cores_pwr_dm_suspend();
+ }
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_rockchip_gic_cpuif_disable();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_cci_disable();
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void rockchip_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_on_finish)
+ rockchip_ops->cores_pwr_dm_on_finish();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ }
+
+ /* Enable the gic cpu interface */
+ plat_rockchip_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_rockchip_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+void rockchip_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ /* Nothing to be done on waking up from retention from CPU level */
+ if (RK_CORE_PWR_STATE(target_state) == PLAT_MAX_RET_STATE)
+ return;
+
+ /* Perform system domain restore if woken up from system suspend */
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_rockchip_sys_pwr_domain_resume();
+ else
+ plat_rockchip_cores_pwr_domain_resume();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ }
+}
+
+/*******************************************************************************
+ * RockChip handlers to reboot the system
+ ******************************************************************************/
+static void __dead2 rockchip_system_reset(void)
+{
+ assert(rockchip_ops && rockchip_ops->sys_gbl_soft_reset);
+
+ rockchip_ops->sys_gbl_soft_reset();
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip
+ * standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+const plat_psci_ops_t plat_rockchip_psci_pm_ops = {
+ .cpu_standby = rockchip_cpu_standby,
+ .pwr_domain_on = rockchip_pwr_domain_on,
+ .pwr_domain_off = rockchip_pwr_domain_off,
+ .pwr_domain_suspend = rockchip_pwr_domain_suspend,
+ .pwr_domain_on_finish = rockchip_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish,
+ .system_reset = rockchip_system_reset,
+ .validate_power_state = rockchip_validate_power_state,
+ .get_sys_suspend_power_state = rockchip_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_rockchip_psci_pm_ops;
+ rockchip_sec_entrypoint = sec_entrypoint;
+ return 0;
+}
+
+void plat_setup_rockchip_pm_ops(struct rockchip_pm_ops_cb *ops)
+{
+ rockchip_ops = ops;
+}
diff --git a/plat/rockchip/common/plat_topology.c b/plat/rockchip/common/plat_topology.c
new file mode 100644
index 0000000..911978a
--- /dev/null
+++ b/plat/rockchip/common/plat_topology.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013-2016, 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 <arch.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <psci.h>
+
+/*******************************************************************************
+ * This function returns the RockChip default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rockchip_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+ cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ return ((cluster_id * PLATFORM_CLUSTER0_CORE_COUNT) + cpu_id);
+}
diff --git a/plat/rockchip/common/pmusram/pmu_sram.c b/plat/rockchip/common/pmusram/pmu_sram.c
new file mode 100644
index 0000000..bea4875
--- /dev/null
+++ b/plat/rockchip/common/pmusram/pmu_sram.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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 <platform.h>
+
+/*****************************************************************************
+ * sram only surpport 32-bits access
+ ******************************************************************************/
+void u32_align_cpy(uint32_t *dst, const uint32_t *src, size_t bytes)
+{
+ uint32_t i;
+
+ for (i = 0; i < bytes; i++)
+ dst[i] = src[i];
+}
diff --git a/plat/rockchip/common/pmusram/pmu_sram.h b/plat/rockchip/common/pmusram/pmu_sram.h
new file mode 100644
index 0000000..a2ab460
--- /dev/null
+++ b/plat/rockchip/common/pmusram/pmu_sram.h
@@ -0,0 +1,91 @@
+/* Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+
+#ifndef __PMU_SRAM_H__
+#define __PMU_SRAM_H__
+
+/*****************************************************************************
+ * cpu up status
+ *****************************************************************************/
+#define PMU_SYS_SLP_MODE 0xa5
+#define PMU_SYS_ON_MODE 0x0
+
+/*****************************************************************************
+ * define data offset in struct psram_data
+ *****************************************************************************/
+#define PSRAM_DT_SP 0x0
+#define PSRAM_DT_DDR_FUNC 0x8
+#define PSRAM_DT_DDR_DATA 0x10
+#define PSRAM_DT_DDRFLAG 0x18
+#define PSRAM_DT_SYS_MODE 0x1c
+#define PSRAM_DT_MPIDR 0x20
+#define PSRAM_DT_END 0x24
+/******************************************************************************
+ * Allocate data region for struct psram_data_t in pmusram
+ ******************************************************************************/
+/* Needed aligned 16 bytes for sp stack top */
+#define PSRAM_DT_SIZE (((PSRAM_DT_END + 16) / 16) * 16)
+#define PSRAM_DT_BASE ((PMUSRAM_BASE + PMUSRAM_RSIZE) - PSRAM_DT_SIZE)
+#define PSRAM_SP_TOP PSRAM_DT_BASE
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The struct is used in pmu_cpus_on.S which
+ * gets the data of the struct by the following index
+ * #define PSRAM_DT_SP 0x0
+ * #define PSRAM_DT_DDR_FUNC 0x8
+ * #define PSRAM_DT_DDR_DATA 0x10
+ * #define PSRAM_DT_DDRFLAG 0x18
+ * #define PSRAM_DT_SYS_MODE 0x1c
+ * #define PSRAM_DT_MPIDR 0x20
+ */
+struct psram_data_t {
+ uint64_t sp;
+ uint64_t ddr_func;
+ uint64_t ddr_data;
+ uint32_t ddr_flag;
+ uint32_t sys_mode;
+ uint32_t boot_mpidr;
+};
+
+CASSERT(sizeof(struct psram_data_t) <= PSRAM_DT_SIZE,
+ assert_psram_dt_size_mismatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, sp) == PSRAM_DT_SP,
+ assert_psram_dt_sp_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_func) == PSRAM_DT_DDR_FUNC,
+ assert_psram_dt_ddr_func_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_data) == PSRAM_DT_DDR_DATA,
+ assert_psram_dt_ddr_data_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_flag) == PSRAM_DT_DDRFLAG,
+ assert_psram_dt_ddr_flag_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, sys_mode) == PSRAM_DT_SYS_MODE,
+ assert_psram_dt_sys_mode_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, boot_mpidr) == PSRAM_DT_MPIDR,
+ assert_psram_dt_mpidr_offset_mistmatch);
+void u32_align_cpy(uint32_t *dst, const uint32_t *src, size_t bytes);
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
new file mode 100644
index 0000000..33a4646
--- /dev/null
+++ b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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 <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <pmu_sram.h>
+
+ .globl pmu_cpuson_entrypoint_start
+ .globl pmu_cpuson_entrypoint_end
+
+func pmu_cpuson_entrypoint
+pmu_cpuson_entrypoint_start:
+ ldr x5, psram_data
+ ldr w0, [x5, #PSRAM_DT_SYS_MODE]
+ cmp w0, #PMU_SYS_SLP_MODE
+ b.eq check_wake_cpus
+ ldr x6, warm_boot_func
+ br x6
+check_wake_cpus:
+ mrs x0, MPIDR_EL1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ orr x0, x0, x1
+ /* primary_cpu */
+ ldr w1, [x5, #PSRAM_DT_MPIDR]
+ cmp w0, w1
+ b.eq sys_wakeup
+ /*
+ * If the core is not the primary cpu,
+ * force the core into wfe.
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+sys_wakeup:
+ /* check ddr flag for resume ddr */
+ ldr w2, [x5, #PSRAM_DT_DDRFLAG]
+ cmp w2, #0x0
+ b.eq sys_resume
+ddr_resume:
+ ldr x2, [x5, #PSRAM_DT_SP]
+ mov sp, x2
+ ldr x1, [x5, #PSRAM_DT_DDR_FUNC]
+ ldr x0, [x5, #PSRAM_DT_DDR_DATA]
+ blr x1
+sys_resume:
+ ldr x1, sys_wakeup_entry
+ br x1
+
+ .align 3
+psram_data:
+ .quad PSRAM_DT_BASE
+warm_boot_func:
+ .quad platform_cpu_warmboot
+sys_wakeup_entry:
+ .quad psci_entrypoint
+pmu_cpuson_entrypoint_end:
+ .word 0
+endfunc pmu_cpuson_entrypoint
diff --git a/plat/rockchip/common/rockchip_gicv2.c b/plat/rockchip/common/rockchip_gicv2.c
new file mode 100644
index 0000000..3e1fa91
--- /dev/null
+++ b/plat/rockchip/common/rockchip_gicv2.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016, 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 <bl_common.h>
+#include <gicv2.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv2 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_rockchip_gic_driver_init
+#pragma weak plat_rockchip_gic_init
+#pragma weak plat_rockchip_gic_cpuif_enable
+#pragma weak plat_rockchip_gic_cpuif_disable
+#pragma weak plat_rockchip_gic_pcpu_init
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+const unsigned int g0_interrupt_array[] = {
+ PLAT_RK_G1S_IRQS,
+};
+
+/*
+ * Ideally `rockchip_gic_data` structure definition should be a `const` but it
+ * is kept as modifiable for overwriting with different GICD and GICC base when
+ * running on FVP with VE memory map.
+ */
+gicv2_driver_data_t rockchip_gic_data = {
+ .gicd_base = PLAT_RK_GICD_BASE,
+ .gicc_base = PLAT_RK_GICC_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+ .g0_interrupt_array = g0_interrupt_array,
+};
+
+/******************************************************************************
+ * RockChip common helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void plat_rockchip_gic_driver_init(void)
+{
+ gicv2_driver_init(&rockchip_gic_data);
+}
+
+void plat_rockchip_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * RockChip common helper to enable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * RockChip common helper to disable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_disable(void)
+{
+ gicv2_cpuif_disable();
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the per cpu distributor interface
+ * in GICv2
+ *****************************************************************************/
+void plat_rockchip_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+}
diff --git a/plat/rockchip/common/rockchip_gicv3.c b/plat/rockchip/common/rockchip_gicv3.c
new file mode 100644
index 0000000..d197aba
--- /dev/null
+++ b/plat/rockchip/common/rockchip_gicv3.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, 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 <bl_common.h>
+#include <gicv3.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_rockchip_gic_driver_init
+#pragma weak plat_rockchip_gic_init
+#pragma weak plat_rockchip_gic_cpuif_enable
+#pragma weak plat_rockchip_gic_cpuif_disable
+#pragma weak plat_rockchip_gic_pcpu_init
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* Array of Group1 secure interrupts to be configured by the gic driver */
+const unsigned int g1s_interrupt_array[] = {
+ PLAT_RK_G1S_IRQS
+};
+
+/* Array of Group0 interrupts to be configured by the gic driver */
+const unsigned int g0_interrupt_array[] = {
+ PLAT_RK_G0_IRQS
+};
+
+static unsigned int plat_rockchip_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+const gicv3_driver_data_t rockchip_gic_data = {
+ .gicd_base = PLAT_RK_GICD_BASE,
+ .gicr_base = PLAT_RK_GICR_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+ .g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
+ .g0_interrupt_array = g0_interrupt_array,
+ .g1s_interrupt_array = g1s_interrupt_array,
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = plat_rockchip_mpidr_to_core_pos,
+};
+
+void plat_rockchip_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if IMAGE_BL31
+ gicv3_driver_init(&rockchip_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the GIC. Only invoked
+ * by BL31
+ *****************************************************************************/
+void plat_rockchip_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the per-cpu redistributor interface
+ * in GICv3
+ *****************************************************************************/
+void plat_rockchip_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c
new file mode 100644
index 0000000..cb89575
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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 <mmio.h>
+#include <ddr_rk3368.h>
+#include <debug.h>
+#include <stdint.h>
+#include <string.h>
+#include <platform_def.h>
+#include <pmu.h>
+#include <rk3368_def.h>
+#include <soc.h>
+
+/* GRF_SOC_STATUS0 */
+#define DPLL_LOCK (0x1 << 2)
+
+/* GRF_DDRC0_CON0 */
+#define GRF_DDR_16BIT_EN (((0x1 << 3) << 16) | (0x1 << 3))
+#define GRF_DDR_32BIT_EN (((0x1 << 3) << 16) | (0x0 << 3))
+#define GRF_MOBILE_DDR_EN (((0x1 << 4) << 16) | (0x1 << 4))
+#define GRF_MOBILE_DDR_DISB (((0x1 << 4) << 16) | (0x0 << 4))
+#define GRF_DDR3_EN (((0x1 << 2) << 16) | (0x1 << 2))
+#define GRF_LPDDR2_3_EN (((0x1 << 2) << 16) | (0x0 << 2))
+
+/* PMUGRF_SOC_CON0 */
+#define ddrphy_bufferen_io_en(n) ((0x1 << (9 + 16)) | (n << 9))
+#define ddrphy_bufferen_core_en(n) ((0x1 << (8 + 16)) | (n << 8))
+
+struct PCTRL_TIMING_TAG {
+ uint32_t ddrfreq;
+ uint32_t TOGCNT1U;
+ uint32_t TINIT;
+ uint32_t TRSTH;
+ uint32_t TOGCNT100N;
+ uint32_t TREFI;
+ uint32_t TMRD;
+ uint32_t TRFC;
+ uint32_t TRP;
+ uint32_t TRTW;
+ uint32_t TAL;
+ uint32_t TCL;
+ uint32_t TCWL;
+ uint32_t TRAS;
+ uint32_t TRC;
+ uint32_t TRCD;
+ uint32_t TRRD;
+ uint32_t TRTP;
+ uint32_t TWR;
+ uint32_t TWTR;
+ uint32_t TEXSR;
+ uint32_t TXP;
+ uint32_t TXPDLL;
+ uint32_t TZQCS;
+ uint32_t TZQCSI;
+ uint32_t TDQS;
+ uint32_t TCKSRE;
+ uint32_t TCKSRX;
+ uint32_t TCKE;
+ uint32_t TMOD;
+ uint32_t TRSTL;
+ uint32_t TZQCL;
+ uint32_t TMRR;
+ uint32_t TCKESR;
+ uint32_t TDPD;
+ uint32_t TREFI_MEM_DDR3;
+};
+
+struct MSCH_SAVE_REG_TAG {
+ uint32_t ddrconf;
+ uint32_t ddrtiming;
+ uint32_t ddrmode;
+ uint32_t readlatency;
+ uint32_t activate;
+ uint32_t devtodev;
+};
+
+/* ddr suspend need save reg */
+struct PCTL_SAVE_REG_TAG {
+ uint32_t SCFG;
+ uint32_t CMDTSTATEN;
+ uint32_t MCFG1;
+ uint32_t MCFG;
+ uint32_t PPCFG;
+ struct PCTRL_TIMING_TAG pctl_timing;
+ /* DFI Control Registers */
+ uint32_t DFITCTRLDELAY;
+ uint32_t DFIODTCFG;
+ uint32_t DFIODTCFG1;
+ uint32_t DFIODTRANKMAP;
+ /* DFI Write Data Registers */
+ uint32_t DFITPHYWRDATA;
+ uint32_t DFITPHYWRLAT;
+ uint32_t DFITPHYWRDATALAT;
+ /* DFI Read Data Registers */
+ uint32_t DFITRDDATAEN;
+ uint32_t DFITPHYRDLAT;
+ /* DFI Update Registers */
+ uint32_t DFITPHYUPDTYPE0;
+ uint32_t DFITPHYUPDTYPE1;
+ uint32_t DFITPHYUPDTYPE2;
+ uint32_t DFITPHYUPDTYPE3;
+ uint32_t DFITCTRLUPDMIN;
+ uint32_t DFITCTRLUPDMAX;
+ uint32_t DFITCTRLUPDDLY;
+ uint32_t DFIUPDCFG;
+ uint32_t DFITREFMSKI;
+ uint32_t DFITCTRLUPDI;
+ /* DFI Status Registers */
+ uint32_t DFISTCFG0;
+ uint32_t DFISTCFG1;
+ uint32_t DFITDRAMCLKEN;
+ uint32_t DFITDRAMCLKDIS;
+ uint32_t DFISTCFG2;
+ /* DFI Low Power Register */
+ uint32_t DFILPCFG0;
+};
+
+struct DDRPHY_SAVE_REG_TAG {
+ uint32_t PHY_REG0;
+ uint32_t PHY_REG1;
+ uint32_t PHY_REGB;
+ uint32_t PHY_REGC;
+ uint32_t PHY_REG11;
+ uint32_t PHY_REG13;
+ uint32_t PHY_REG14;
+ uint32_t PHY_REG16;
+ uint32_t PHY_REG20;
+ uint32_t PHY_REG21;
+ uint32_t PHY_REG26;
+ uint32_t PHY_REG27;
+ uint32_t PHY_REG28;
+ uint32_t PHY_REG30;
+ uint32_t PHY_REG31;
+ uint32_t PHY_REG36;
+ uint32_t PHY_REG37;
+ uint32_t PHY_REG38;
+ uint32_t PHY_REG40;
+ uint32_t PHY_REG41;
+ uint32_t PHY_REG46;
+ uint32_t PHY_REG47;
+ uint32_t PHY_REG48;
+ uint32_t PHY_REG50;
+ uint32_t PHY_REG51;
+ uint32_t PHY_REG56;
+ uint32_t PHY_REG57;
+ uint32_t PHY_REG58;
+ uint32_t PHY_REGDLL;
+ uint32_t PHY_REGEC;
+ uint32_t PHY_REGED;
+ uint32_t PHY_REGEE;
+ uint32_t PHY_REGEF;
+ uint32_t PHY_REGFB;
+ uint32_t PHY_REGFC;
+ uint32_t PHY_REGFD;
+ uint32_t PHY_REGFE;
+};
+
+struct BACKUP_REG_TAG {
+ uint32_t tag;
+ uint32_t pctladdr;
+ struct PCTL_SAVE_REG_TAG pctl;
+ uint32_t phyaddr;
+ struct DDRPHY_SAVE_REG_TAG phy;
+ uint32_t nocaddr;
+ struct MSCH_SAVE_REG_TAG noc;
+ uint32_t pllselect;
+ uint32_t phypllockaddr;
+ uint32_t phyplllockmask;
+ uint32_t phyplllockval;
+ uint32_t pllpdstat;
+ uint32_t dpllmodeaddr;
+ uint32_t dpllslowmode;
+ uint32_t dpllnormalmode;
+ uint32_t dpllresetaddr;
+ uint32_t dpllreset;
+ uint32_t dplldereset;
+ uint32_t dpllconaddr;
+ uint32_t dpllcon[4];
+ uint32_t dplllockaddr;
+ uint32_t dplllockmask;
+ uint32_t dplllockval;
+ uint32_t ddrpllsrcdivaddr;
+ uint32_t ddrpllsrcdiv;
+ uint32_t retendisaddr;
+ uint32_t retendisval;
+ uint32_t grfregaddr;
+ uint32_t grfddrcreg;
+ uint32_t crupctlphysoftrstaddr;
+ uint32_t cruresetpctlphy;
+ uint32_t cruderesetphy;
+ uint32_t cruderesetpctlphy;
+ uint32_t physoftrstaddr;
+ uint32_t endtag;
+};
+
+static uint32_t ddr_get_phy_pll_freq(void)
+{
+ uint32_t ret = 0;
+ uint32_t fb_div, pre_div;
+
+ fb_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC);
+ fb_div |= (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED) & 0x1) << 8;
+
+ pre_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) & 0xff;
+ ret = 2 * 24 * fb_div / (4 * pre_div);
+
+ return ret;
+}
+
+static void ddr_copy(uint32_t *pdest, uint32_t *psrc, uint32_t words)
+{
+ uint32_t i;
+
+ for (i = 0; i < words; i++)
+ pdest[i] = psrc[i];
+}
+
+static void ddr_get_dpll_cfg(uint32_t *p)
+{
+ uint32_t nmhz, NO, NF, NR;
+
+ nmhz = ddr_get_phy_pll_freq();
+ if (nmhz <= 150)
+ NO = 6;
+ else if (nmhz <= 250)
+ NO = 4;
+ else if (nmhz <= 500)
+ NO = 2;
+ else
+ NO = 1;
+
+ NR = 1;
+ NF = 2 * nmhz * NR * NO / 24;
+
+ p[0] = SET_NR(NR) | SET_NO(NO);
+ p[1] = SET_NF(NF);
+ p[2] = SET_NB(NF / 2);
+}
+
+void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr)
+{
+ struct BACKUP_REG_TAG *p_ddr_reg = (struct BACKUP_REG_TAG *)base_addr;
+ struct PCTL_SAVE_REG_TAG *pctl_tim = &p_ddr_reg->pctl;
+
+ p_ddr_reg->tag = 0x56313031;
+ p_ddr_reg->pctladdr = DDR_PCTL_BASE;
+ p_ddr_reg->phyaddr = DDR_PHY_BASE;
+ p_ddr_reg->nocaddr = SERVICE_BUS_BASE;
+
+ /* PCTLR */
+ ddr_copy((uint32_t *)&pctl_tim->pctl_timing.TOGCNT1U,
+ (uint32_t *)(DDR_PCTL_BASE + DDR_PCTL_TOGCNT1U), 35);
+ pctl_tim->pctl_timing.TREFI |= DDR_UPD_REF_ENABLE;
+ pctl_tim->SCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_SCFG);
+ pctl_tim->CMDTSTATEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_CMDTSTATEN);
+ pctl_tim->MCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG1);
+ pctl_tim->MCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG);
+ pctl_tim->PPCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_PPCFG);
+ pctl_tim->pctl_timing.ddrfreq = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_TOGCNT1U * 2);
+ pctl_tim->DFITCTRLDELAY = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLDELAY);
+ pctl_tim->DFIODTCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIODTCFG);
+ pctl_tim->DFIODTCFG1 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFIODTCFG1);
+ pctl_tim->DFIODTRANKMAP = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFIODTRANKMAP);
+ pctl_tim->DFITPHYWRDATA = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRDATA);
+ pctl_tim->DFITPHYWRLAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRLAT);
+ pctl_tim->DFITPHYWRDATALAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRDATALAT);
+ pctl_tim->DFITRDDATAEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITRDDATAEN);
+ pctl_tim->DFITPHYRDLAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYRDLAT);
+ pctl_tim->DFITPHYUPDTYPE0 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE0);
+ pctl_tim->DFITPHYUPDTYPE1 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE1);
+ pctl_tim->DFITPHYUPDTYPE2 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE2);
+ pctl_tim->DFITPHYUPDTYPE3 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE3);
+ pctl_tim->DFITCTRLUPDMIN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDMIN);
+ pctl_tim->DFITCTRLUPDMAX = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDMAX);
+ pctl_tim->DFITCTRLUPDDLY = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDDLY);
+
+ pctl_tim->DFIUPDCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIUPDCFG);
+ pctl_tim->DFITREFMSKI = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITREFMSKI);
+ pctl_tim->DFITCTRLUPDI = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDI);
+ pctl_tim->DFISTCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG0);
+ pctl_tim->DFISTCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG1);
+ pctl_tim->DFITDRAMCLKEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITDRAMCLKEN);
+ pctl_tim->DFITDRAMCLKDIS = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITDRAMCLKDIS);
+ pctl_tim->DFISTCFG2 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG2);
+ pctl_tim->DFILPCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFILPCFG0);
+
+ /* PHY */
+ p_ddr_reg->phy.PHY_REG0 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG0);
+ p_ddr_reg->phy.PHY_REG1 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG1);
+ p_ddr_reg->phy.PHY_REGB = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGB);
+ p_ddr_reg->phy.PHY_REGC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGC);
+ p_ddr_reg->phy.PHY_REG11 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG11);
+ p_ddr_reg->phy.PHY_REG13 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG13);
+ p_ddr_reg->phy.PHY_REG14 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG14);
+ p_ddr_reg->phy.PHY_REG16 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG16);
+ p_ddr_reg->phy.PHY_REG20 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG20);
+ p_ddr_reg->phy.PHY_REG21 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG21);
+ p_ddr_reg->phy.PHY_REG26 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG26);
+ p_ddr_reg->phy.PHY_REG27 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG27);
+ p_ddr_reg->phy.PHY_REG28 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG28);
+ p_ddr_reg->phy.PHY_REG30 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG30);
+ p_ddr_reg->phy.PHY_REG31 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG31);
+ p_ddr_reg->phy.PHY_REG36 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG36);
+ p_ddr_reg->phy.PHY_REG37 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG37);
+ p_ddr_reg->phy.PHY_REG38 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG38);
+ p_ddr_reg->phy.PHY_REG40 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG40);
+ p_ddr_reg->phy.PHY_REG41 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG41);
+ p_ddr_reg->phy.PHY_REG46 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG46);
+ p_ddr_reg->phy.PHY_REG47 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG47);
+ p_ddr_reg->phy.PHY_REG48 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG48);
+ p_ddr_reg->phy.PHY_REG50 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG50);
+ p_ddr_reg->phy.PHY_REG51 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG51);
+ p_ddr_reg->phy.PHY_REG56 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG56);
+ p_ddr_reg->phy.PHY_REG57 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG57);
+ p_ddr_reg->phy.PHY_REG58 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG58);
+ p_ddr_reg->phy.PHY_REGDLL = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGDLL);
+ p_ddr_reg->phy.PHY_REGEC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC);
+ p_ddr_reg->phy.PHY_REGED = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED);
+ p_ddr_reg->phy.PHY_REGEE = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE);
+ p_ddr_reg->phy.PHY_REGEF = 0;
+
+ if (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG2) & 0x2) {
+ p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG2C);
+ p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG3C);
+ p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG4C);
+ p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG5C);
+ } else {
+ p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFB);
+ p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFC);
+ p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFD);
+ p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFE);
+ }
+
+ /* NOC */
+ p_ddr_reg->noc.ddrconf = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRCONF);
+ p_ddr_reg->noc.ddrtiming = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_DDRTIMING);
+ p_ddr_reg->noc.ddrmode = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRMODE);
+ p_ddr_reg->noc.readlatency = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_READLATENCY);
+ p_ddr_reg->noc.activate = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_ACTIVATE);
+ p_ddr_reg->noc.devtodev = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_DEVTODEV);
+
+ p_ddr_reg->pllselect = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) * 0x1;
+ p_ddr_reg->phypllockaddr = GRF_BASE + GRF_SOC_STATUS0;
+ p_ddr_reg->phyplllockmask = GRF_DDRPHY_LOCK;
+ p_ddr_reg->phyplllockval = 0;
+
+ /* PLLPD */
+ p_ddr_reg->pllpdstat = pllpdstat;
+ /* DPLL */
+ p_ddr_reg->dpllmodeaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3);
+ /* slow mode and power on */
+ p_ddr_reg->dpllslowmode = DPLL_WORK_SLOW_MODE | DPLL_POWER_DOWN;
+ p_ddr_reg->dpllnormalmode = DPLL_WORK_NORMAL_MODE;
+ p_ddr_reg->dpllresetaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3);
+ p_ddr_reg->dpllreset = DPLL_RESET_CONTROL_NORMAL;
+ p_ddr_reg->dplldereset = DPLL_RESET_CONTROL_RESET;
+ p_ddr_reg->dpllconaddr = CRU_BASE + PLL_CONS(DPLL_ID, 0);
+
+ if (p_ddr_reg->pllselect == 0) {
+ p_ddr_reg->dpllcon[0] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 0))
+ & 0xffff) |
+ (0xFFFF << 16);
+ p_ddr_reg->dpllcon[1] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 1))
+ & 0xffff);
+ p_ddr_reg->dpllcon[2] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 2))
+ & 0xffff);
+ p_ddr_reg->dpllcon[3] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 3))
+ & 0xffff) |
+ (0xFFFF << 16);
+ } else {
+ ddr_get_dpll_cfg(&p_ddr_reg->dpllcon[0]);
+ }
+
+ p_ddr_reg->pllselect = 0;
+ p_ddr_reg->dplllockaddr = CRU_BASE + PLL_CONS(DPLL_ID, 1);
+ p_ddr_reg->dplllockmask = DPLL_STATUS_LOCK;
+ p_ddr_reg->dplllockval = DPLL_STATUS_LOCK;
+
+ /* SET_DDR_PLL_SRC */
+ p_ddr_reg->ddrpllsrcdivaddr = CRU_BASE + CRU_CLKSELS_CON(13);
+ p_ddr_reg->ddrpllsrcdiv = (mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(13))
+ & DDR_PLL_SRC_MASK)
+ | (DDR_PLL_SRC_MASK << 16);
+ p_ddr_reg->retendisaddr = PMU_BASE + PMU_PWRMD_COM;
+ p_ddr_reg->retendisval = PD_PERI_PWRDN_ENABLE;
+ p_ddr_reg->grfregaddr = GRF_BASE + GRF_DDRC0_CON0;
+ p_ddr_reg->grfddrcreg = (mmio_read_32(GRF_BASE + GRF_DDRC0_CON0) &
+ DDR_PLL_SRC_MASK) |
+ (DDR_PLL_SRC_MASK << 16);
+
+ /* pctl phy soft reset */
+ p_ddr_reg->crupctlphysoftrstaddr = CRU_BASE + CRU_SOFTRSTS_CON(10);
+ p_ddr_reg->cruresetpctlphy = DDRCTRL0_PSRSTN_REQ(1) |
+ DDRCTRL0_SRSTN_REQ(1) |
+ DDRPHY0_PSRSTN_REQ(1) |
+ DDRPHY0_SRSTN_REQ(1);
+ p_ddr_reg->cruderesetphy = DDRCTRL0_PSRSTN_REQ(1) |
+ DDRCTRL0_SRSTN_REQ(1) |
+ DDRPHY0_PSRSTN_REQ(0) |
+ DDRPHY0_SRSTN_REQ(0);
+
+ p_ddr_reg->cruderesetpctlphy = DDRCTRL0_PSRSTN_REQ(0) |
+ DDRCTRL0_SRSTN_REQ(0) |
+ DDRPHY0_PSRSTN_REQ(0) |
+ DDRPHY0_SRSTN_REQ(0);
+
+ p_ddr_reg->physoftrstaddr = DDR_PHY_BASE + DDR_PHY_REG0;
+
+ p_ddr_reg->endtag = 0xFFFFFFFF;
+}
+
+/*
+ * "rk3368_ddr_reg_resume_V1.05.bin" is an executable bin which is generated
+ * by ARM DS5 for resuming ddr controller. If the soc wakes up from system
+ * suspend, ddr needs to be resumed and the resuming code needs to be run in
+ * sram. But there is not a way to pointing the resuming code to the PMUSRAM
+ * when linking .o files of bl31, so we use the
+ * "rk3368_ddr_reg_resume_V1.05.bin" whose code is position-independent and
+ * it can be loaded anywhere and run.
+ */
+static __aligned(4) unsigned int ddr_reg_resume[] = {
+ #include "rk3368_ddr_reg_resume_V1.05.bin"
+};
+
+uint32_t ddr_get_resume_code_size(void)
+{
+ return sizeof(ddr_reg_resume);
+}
+
+uint32_t ddr_get_resume_data_size(void)
+{
+ return sizeof(struct BACKUP_REG_TAG);
+}
+
+uint32_t *ddr_get_resume_code_base(void)
+{
+ return (unsigned int *)ddr_reg_resume;
+}
diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h
new file mode 100644
index 0000000..c9d6c25
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+
+#ifndef __DDR_RK3368_H__
+#define __DDR_RK3368_H__
+
+#define DDR_PCTL_SCFG 0x0
+#define DDR_PCTL_SCTL 0x4
+#define DDR_PCTL_STAT 0x8
+#define DDR_PCTL_INTRSTAT 0xc
+
+#define DDR_PCTL_MCMD 0x40
+#define DDR_PCTL_POWCTL 0x44
+#define DDR_PCTL_POWSTAT 0x48
+#define DDR_PCTL_CMDTSTAT 0x4c
+#define DDR_PCTL_CMDTSTATEN 0x50
+#define DDR_PCTL_MRRCFG0 0x60
+#define DDR_PCTL_MRRSTAT0 0x64
+#define DDR_PCTL_MRRSTAT1 0x68
+#define DDR_PCTL_MCFG1 0x7c
+#define DDR_PCTL_MCFG 0x80
+#define DDR_PCTL_PPCFG 0x84
+#define DDR_PCTL_MSTAT 0x88
+#define DDR_PCTL_LPDDR2ZQCFG 0x8c
+#define DDR_PCTL_DTUPDES 0x94
+#define DDR_PCTL_DTUNA 0x98
+#define DDR_PCTL_DTUNE 0x9c
+#define DDR_PCTL_DTUPRD0 0xa0
+#define DDR_PCTL_DTUPRD1 0xa4
+#define DDR_PCTL_DTUPRD2 0xa8
+#define DDR_PCTL_DTUPRD3 0xac
+#define DDR_PCTL_DTUAWDT 0xb0
+#define DDR_PCTL_TOGCNT1U 0xc0
+#define DDR_PCTL_TINIT 0xc4
+#define DDR_PCTL_TRSTH 0xc8
+#define DDR_PCTL_TOGCNT100N 0xcc
+#define DDR_PCTL_TREFI 0xd0
+#define DDR_PCTL_TMRD 0xd4
+#define DDR_PCTL_TRFC 0xd8
+#define DDR_PCTL_TRP 0xdc
+#define DDR_PCTL_TRTW 0xe0
+#define DDR_PCTL_TAL 0xe4
+#define DDR_PCTL_TCL 0xe8
+#define DDR_PCTL_TCWL 0xec
+#define DDR_PCTL_TRAS 0xf0
+#define DDR_PCTL_TRC 0xf4
+#define DDR_PCTL_TRCD 0xf8
+#define DDR_PCTL_TRRD 0xfc
+#define DDR_PCTL_TRTP 0x100
+#define DDR_PCTL_TWR 0x104
+#define DDR_PCTL_TWTR 0x108
+#define DDR_PCTL_TEXSR 0x10c
+#define DDR_PCTL_TXP 0x110
+#define DDR_PCTL_TXPDLL 0x114
+#define DDR_PCTL_TZQCS 0x118
+#define DDR_PCTL_TZQCSI 0x11c
+#define DDR_PCTL_TDQS 0x120
+#define DDR_PCTL_TCKSRE 0x124
+#define DDR_PCTL_TCKSRX 0x128
+#define DDR_PCTL_TCKE 0x12c
+#define DDR_PCTL_TMOD 0x130
+#define DDR_PCTL_TRSTL 0x134
+#define DDR_PCTL_TZQCL 0x138
+#define DDR_PCTL_TMRR 0x13c
+#define DDR_PCTL_TCKESR 0x140
+#define DDR_PCTL_TDPD 0x144
+#define DDR_PCTL_TREFI_MEM_DDR3 0x148
+#define DDR_PCTL_ECCCFG 0x180
+#define DDR_PCTL_ECCTST 0x184
+#define DDR_PCTL_ECCCLR 0x188
+#define DDR_PCTL_ECCLOG 0x18c
+#define DDR_PCTL_DTUWACTL 0x200
+#define DDR_PCTL_DTURACTL 0x204
+#define DDR_PCTL_DTUCFG 0x208
+#define DDR_PCTL_DTUECTL 0x20c
+#define DDR_PCTL_DTUWD0 0x210
+#define DDR_PCTL_DTUWD1 0x214
+#define DDR_PCTL_DTUWD2 0x218
+#define DDR_PCTL_DTUWD3 0x21c
+#define DDR_PCTL_DTUWDM 0x220
+#define DDR_PCTL_DTURD0 0x224
+#define DDR_PCTL_DTURD1 0x228
+#define DDR_PCTL_DTURD2 0x22c
+#define DDR_PCTL_DTURD3 0x230
+#define DDR_PCTL_DTULFSRWD 0x234
+#define DDR_PCTL_DTULFSRRD 0x238
+#define DDR_PCTL_DTUEAF 0x23c
+#define DDR_PCTL_DFITCTRLDELAY 0x240
+#define DDR_PCTL_DFIODTCFG 0x244
+#define DDR_PCTL_DFIODTCFG1 0x248
+#define DDR_PCTL_DFIODTRANKMAP 0x24c
+#define DDR_PCTL_DFITPHYWRDATA 0x250
+#define DDR_PCTL_DFITPHYWRLAT 0x254
+#define DDR_PCTL_DFITPHYWRDATALAT 0x258
+#define DDR_PCTL_DFITRDDATAEN 0x260
+#define DDR_PCTL_DFITPHYRDLAT 0x264
+#define DDR_PCTL_DFITPHYUPDTYPE0 0x270
+#define DDR_PCTL_DFITPHYUPDTYPE1 0x274
+#define DDR_PCTL_DFITPHYUPDTYPE2 0x278
+#define DDR_PCTL_DFITPHYUPDTYPE3 0x27c
+#define DDR_PCTL_DFITCTRLUPDMIN 0x280
+#define DDR_PCTL_DFITCTRLUPDMAX 0x284
+#define DDR_PCTL_DFITCTRLUPDDLY 0x288
+#define DDR_PCTL_DFIUPDCFG 0x290
+#define DDR_PCTL_DFITREFMSKI 0x294
+#define DDR_PCTL_DFITCTRLUPDI 0x298
+#define DDR_PCTL_DFITRCFG0 0x2ac
+#define DDR_PCTL_DFITRSTAT0 0x2b0
+#define DDR_PCTL_DFITRWRLVLEN 0x2b4
+#define DDR_PCTL_DFITRRDLVLEN 0x2b8
+#define DDR_PCTL_DFITRRDLVLGATEEN 0x2bc
+#define DDR_PCTL_DFISTSTAT0 0x2c0
+#define DDR_PCTL_DFISTCFG0 0x2c4
+#define DDR_PCTL_DFISTCFG1 0x2c8
+#define DDR_PCTL_DFITDRAMCLKEN 0x2d0
+#define DDR_PCTL_DFITDRAMCLKDIS 0x2d4
+#define DDR_PCTL_DFISTCFG2 0x2d8
+#define DDR_PCTL_DFISTPARCLR 0x2dc
+#define DDR_PCTL_DFISTPARLOG 0x2e0
+#define DDR_PCTL_DFILPCFG0 0x2f0
+#define DDR_PCTL_DFITRWRLVLRESP0 0x300
+#define DDR_PCTL_DFITRWRLVLRESP1 0x304
+#define DDR_PCTL_DFITRWRLVLRESP2 0x308
+#define DDR_PCTL_DFITRRDLVLRESP0 0x30c
+#define DDR_PCTL_DFITRRDLVLRESP1 0x310
+#define DDR_PCTL_DFITRRDLVLRESP2 0x314
+#define DDR_PCTL_DFITRWRLVLDELAY0 0x318
+#define DDR_PCTL_DFITRWRLVLDELAY1 0x31c
+#define DDR_PCTL_DFITRWRLVLDELAY2 0x320
+#define DDR_PCTL_DFITRRDLVLDELAY0 0x324
+#define DDR_PCTL_DFITRRDLVLDELAY1 0x328
+#define DDR_PCTL_DFITRRDLVLDELAY2 0x32c
+#define DDR_PCTL_DFITRRDLVLGATEDELAY0 0x330
+#define DDR_PCTL_DFITRRDLVLGATEDELAY1 0x334
+#define DDR_PCTL_DFITRRDLVLGATEDELAY2 0x338
+#define DDR_PCTL_DFITRCMD 0x33c
+#define DDR_PCTL_IPVR 0x3f8
+#define DDR_PCTL_IPTR 0x3fc
+
+/* DDR PHY REG */
+#define DDR_PHY_REG0 0x0
+#define DDR_PHY_REG1 0x4
+#define DDR_PHY_REG2 0x8
+#define DDR_PHY_REG3 0xc
+#define DDR_PHY_REG4 0x10
+#define DDR_PHY_REG5 0x14
+#define DDR_PHY_REG6 0x18
+#define DDR_PHY_REGB 0x2c
+#define DDR_PHY_REGC 0x30
+#define DDR_PHY_REG11 0x44
+#define DDR_PHY_REG12 0x48
+#define DDR_PHY_REG13 0x4c
+#define DDR_PHY_REG14 0x50
+#define DDR_PHY_REG16 0x58
+#define DDR_PHY_REG20 0x80
+#define DDR_PHY_REG21 0x84
+#define DDR_PHY_REG26 0x98
+#define DDR_PHY_REG27 0x9c
+#define DDR_PHY_REG28 0xa0
+#define DDR_PHY_REG2C 0xb0
+#define DDR_PHY_REG30 0xc0
+#define DDR_PHY_REG31 0xc4
+#define DDR_PHY_REG36 0xd8
+#define DDR_PHY_REG37 0xdc
+#define DDR_PHY_REG38 0xe0
+#define DDR_PHY_REG3C 0xf0
+#define DDR_PHY_REG40 0x100
+#define DDR_PHY_REG41 0x104
+#define DDR_PHY_REG46 0x118
+#define DDR_PHY_REG47 0x11c
+#define DDR_PHY_REG48 0x120
+#define DDR_PHY_REG4C 0x130
+#define DDR_PHY_REG50 0x140
+#define DDR_PHY_REG51 0x144
+#define DDR_PHY_REG56 0x158
+#define DDR_PHY_REG57 0x15c
+#define DDR_PHY_REG58 0x160
+#define DDR_PHY_REG5C 0x170
+#define DDR_PHY_REGDLL 0x290
+#define DDR_PHY_REGEC 0x3b0
+#define DDR_PHY_REGED 0x3b4
+#define DDR_PHY_REGEE 0x3b8
+#define DDR_PHY_REGEF 0x3bc
+#define DDR_PHY_REGF0 0x3c0
+#define DDR_PHY_REGF1 0x3c4
+#define DDR_PHY_REGF2 0x3c8
+#define DDR_PHY_REGFA 0x3e8
+#define DDR_PHY_REGFB 0x3ec
+#define DDR_PHY_REGFC 0x3f0
+#define DDR_PHY_REGFD 0x3f4
+#define DDR_PHY_REGFE 0x3f8
+#define DDR_PHY_REGFF 0x3fc
+
+/* MSCH REG define */
+#define MSCH_COREID 0x0
+#define MSCH_DDRCONF 0x8
+#define MSCH_DDRTIMING 0xc
+#define MSCH_DDRMODE 0x10
+#define MSCH_READLATENCY 0x14
+#define MSCH_ACTIVATE 0x38
+#define MSCH_DEVTODEV 0x3c
+
+#define SET_NR(n) ((0x3f << (8 + 16)) | ((n - 1) << 8))
+#define SET_NO(n) ((0xf << (0 + 16)) | ((n - 1) << 0))
+#define SET_NF(n) ((n - 1) & 0x1fff)
+#define SET_NB(n) ((n - 1) & 0xfff)
+#define PLLMODE(n) ((0x3 << (8 + 16)) | (n << 8))
+
+/* GRF REG define */
+#define GRF_SOC_STATUS0 0x480
+#define GRF_DDRPHY_LOCK (0x1 << 15)
+#define GRF_DDRC0_CON0 0x600
+
+/* CRU softreset ddr pctl, phy */
+#define DDRMSCH0_SRSTN_REQ(n) (((0x1 << 10) << 16) | (n << 10))
+#define DDRCTRL0_PSRSTN_REQ(n) (((0x1 << 3) << 16) | (n << 3))
+#define DDRCTRL0_SRSTN_REQ(n) (((0x1 << 2) << 16) | (n << 2))
+#define DDRPHY0_PSRSTN_REQ(n) (((0x1 << 1) << 16) | (n << 1))
+#define DDRPHY0_SRSTN_REQ(n) (((0x1 << 0) << 16) | (n << 0))
+
+/* CRU_DPLL_CON2 */
+#define DPLL_STATUS_LOCK (1 << 31)
+
+/* CRU_DPLL_CON3 */
+#define DPLL_POWER_DOWN ((0x1 << (1 + 16)) | (0 << 1))
+#define DPLL_WORK_NORMAL_MODE ((0x3 << (8 + 16)) | (0 << 8))
+#define DPLL_WORK_SLOW_MODE ((0x3 << (8 + 16)) | (1 << 8))
+#define DPLL_RESET_CONTROL_NORMAL ((0x1 << (5 + 16)) | (0x0 << 5))
+#define DPLL_RESET_CONTROL_RESET ((0x1 << (5 + 16)) | (0x1 << 5))
+
+/* PMU_PWRDN_CON */
+#define PD_PERI_PWRDN_ENABLE (1 << 13)
+
+#define DDR_PLL_SRC_MASK 0x13
+
+/* DDR_PCTL_TREFI */
+#define DDR_UPD_REF_ENABLE (0X1 << 31)
+
+uint32_t ddr_get_resume_code_size(void);
+uint32_t ddr_get_resume_data_size(void);
+uint32_t *ddr_get_resume_code_base(void);
+void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr);
+
+#endif
diff --git a/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin b/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin
new file mode 100644
index 0000000..cecd694
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin
@@ -0,0 +1,461 @@
+ 0x14000088,
+ 0xd10043ff,
+ 0x5283ffe1,
+ 0x52824902,
+ 0x1b020400,
+ 0x530d7c00,
+ 0xb9000fe0,
+ 0xb9400fe0,
+ 0x340000a0,
+ 0xb9400fe0,
+ 0x51000401,
+ 0xb9000fe1,
+ 0x35ffffa0,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0x340000e2,
+ 0xb9400023,
+ 0xb9000003,
+ 0x91001021,
+ 0x91001000,
+ 0x51000442,
+ 0x35ffff62,
+ 0xd65f03c0,
+ 0xd10043ff,
+ 0xb9400801,
+ 0x12000821,
+ 0xb9000fe1,
+ 0xb9400fe1,
+ 0x7100043f,
+ 0x54000320,
+ 0x52800021,
+ 0x52800082,
+ 0xb9400fe3,
+ 0x34000143,
+ 0x71000c7f,
+ 0x54000100,
+ 0x7100147f,
+ 0x54000161,
+ 0xb9000402,
+ 0xb9400803,
+ 0x12000863,
+ 0x71000c7f,
+ 0x54ffffa1,
+ 0xb9000401,
+ 0xb9400803,
+ 0x12000863,
+ 0x7100047f,
+ 0x54ffffa1,
+ 0xb9400803,
+ 0x12000863,
+ 0xb9000fe3,
+ 0xb9400fe3,
+ 0x7100047f,
+ 0x54fffd61,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0xd10043ff,
+ 0xb9400801,
+ 0x12000821,
+ 0xb9000fe1,
+ 0xb9400fe1,
+ 0x7100143f,
+ 0x54000400,
+ 0x52800021,
+ 0x52800042,
+ 0x52800063,
+ 0xb9400fe4,
+ 0x340000c4,
+ 0x7100049f,
+ 0x54000120,
+ 0x71000c9f,
+ 0x54000180,
+ 0x14000010,
+ 0xb9000401,
+ 0xb9400804,
+ 0x12000884,
+ 0x7100049f,
+ 0x54ffffa1,
+ 0xb9000402,
+ 0xb9400804,
+ 0x12000884,
+ 0x71000c9f,
+ 0x54ffffa1,
+ 0xb9000403,
+ 0xb9400804,
+ 0x12000884,
+ 0x7100149f,
+ 0x54ffffa1,
+ 0xb9400804,
+ 0x12000884,
+ 0xb9000fe4,
+ 0xb9400fe4,
+ 0x7100149f,
+ 0x54fffca1,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0xd10043ff,
+ 0xb9400801,
+ 0x12000821,
+ 0xb9000fe1,
+ 0xb9400fe1,
+ 0x71000c3f,
+ 0x54000400,
+ 0x52800021,
+ 0x52800042,
+ 0x52800083,
+ 0xb9400fe4,
+ 0x34000164,
+ 0x7100049f,
+ 0x540001c0,
+ 0x7100149f,
+ 0x54000221,
+ 0xb9000403,
+ 0xb9400804,
+ 0x12000884,
+ 0x71000c9f,
+ 0x54ffffa1,
+ 0x1400000b,
+ 0xb9000401,
+ 0xb9400804,
+ 0x12000884,
+ 0x7100049f,
+ 0x54ffffa1,
+ 0xb9000402,
+ 0xb9400804,
+ 0x12000884,
+ 0x71000c9f,
+ 0x54ffffa1,
+ 0xb9400804,
+ 0x12000884,
+ 0xb9000fe4,
+ 0xb9400fe4,
+ 0x71000c9f,
+ 0x54fffca1,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0xd10103ff,
+ 0xa9037bfd,
+ 0x9100c3fd,
+ 0xa9025ff6,
+ 0xa90157f4,
+ 0xf90007f3,
+ 0xaa0003f3,
+ 0xb9400674,
+ 0xb9411276,
+ 0xb941c660,
+ 0xb941aa75,
+ 0x7100041f,
+ 0x54000261,
+ 0xb9418e60,
+ 0x321f0000,
+ 0xb903b6c0,
+ 0xb9418a60,
+ 0xb903b2c0,
+ 0xb9419260,
+ 0xb903bac0,
+ 0xb9418e60,
+ 0x121e7800,
+ 0xb903b6c0,
+ 0xb941ca60,
+ 0xb941ce61,
+ 0xb941d262,
+ 0xb9400003,
+ 0xa030023,
+ 0x6b22407f,
+ 0x54ffffa0,
+ 0x1400003b,
+ 0xb941d660,
+ 0x7100041f,
+ 0x54000701,
+ 0xb941da60,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941de61,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb941e660,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941ea61,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb941f260,
+ 0x3100041f,
+ 0x54000120,
+ 0xaa1f03e1,
+ 0x53007c00,
+ 0x9107d262,
+ 0xb8616843,
+ 0xb8216803,
+ 0x91001021,
+ 0xf100203f,
+ 0x54ffff81,
+ 0x52800020,
+ 0x97ffff3f,
+ 0xb941e660,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941ee61,
+ 0x53007c00,
+ 0xb9000001,
+ 0x52800020,
+ 0x97ffff37,
+ 0xb9420660,
+ 0x3100041f,
+ 0x54000100,
+ 0xb9420a61,
+ 0xb9420e62,
+ 0x53007c00,
+ 0xb9400003,
+ 0xa030023,
+ 0x6b22407f,
+ 0x54ffffa1,
+ 0xb9421260,
+ 0x3100041f,
+ 0x54000080,
+ 0xb9421661,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb941da60,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941e261,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb9419660,
+ 0xb903bec0,
+ 0xb9422a60,
+ 0x34000400,
+ 0xb9422e61,
+ 0x53007c17,
+ 0xb90002e1,
+ 0x52800140,
+ 0x97ffff18,
+ 0xb9423260,
+ 0xb90002e0,
+ 0x52800140,
+ 0x97ffff14,
+ 0xb9423660,
+ 0xb90002e0,
+ 0x52800140,
+ 0x97ffff10,
+ 0xb9423a60,
+ 0x34000220,
+ 0x53007c17,
+ 0xb94002e0,
+ 0x121c7400,
+ 0xb90002e0,
+ 0x52800020,
+ 0x97ffff08,
+ 0xb94002e0,
+ 0x321e0000,
+ 0xb90002e0,
+ 0x528000a0,
+ 0x97ffff03,
+ 0xb94002e0,
+ 0x321d0000,
+ 0xb90002e0,
+ 0x52800020,
+ 0x97fffefe,
+ 0xb9412a60,
+ 0xb9004ec0,
+ 0xb9412e60,
+ 0xb90052c0,
+ 0xb9413e60,
+ 0xb9009ac0,
+ 0xb9414260,
+ 0xb9009ec0,
+ 0xb9415260,
+ 0xb900dac0,
+ 0xb9415660,
+ 0xb900dec0,
+ 0xb9416660,
+ 0xb9011ac0,
+ 0xb9416a60,
+ 0xb9011ec0,
+ 0xb9417a60,
+ 0xb9015ac0,
+ 0xb9417e60,
+ 0xb9015ec0,
+ 0xb9418660,
+ 0xb90292c0,
+ 0xb9414660,
+ 0xb900a2c0,
+ 0xb9415a60,
+ 0xb900e2c0,
+ 0xb9416e60,
+ 0xb90122c0,
+ 0xb9418260,
+ 0xb90162c0,
+ 0xb9411660,
+ 0xb90002c0,
+ 0xb9411a60,
+ 0xb90006c0,
+ 0xb9411e60,
+ 0xb9002ec0,
+ 0xb9412260,
+ 0xb90032c0,
+ 0xb9412660,
+ 0xb90046c0,
+ 0xb9413260,
+ 0xb9005ac0,
+ 0xb9413660,
+ 0xb90082c0,
+ 0xb9413a60,
+ 0xb90086c0,
+ 0xb9414a60,
+ 0xb900c2c0,
+ 0xb9414e60,
+ 0xb900c6c0,
+ 0xb9415e60,
+ 0xb90102c0,
+ 0xb9416260,
+ 0xb90106c0,
+ 0xb9417260,
+ 0xb90142c0,
+ 0xb9417660,
+ 0xb90146c0,
+ 0x52800040,
+ 0xb9000ac0,
+ 0xb9411261,
+ 0xb9419a60,
+ 0xb900b020,
+ 0xb9419a60,
+ 0xb900b420,
+ 0xb9419e60,
+ 0xb900f020,
+ 0xb9419e60,
+ 0xb900f420,
+ 0xb941a260,
+ 0xb9013020,
+ 0xb941a260,
+ 0xb9013420,
+ 0xb941a660,
+ 0xb9017020,
+ 0xb941a662,
+ 0xaa1f03e0,
+ 0xb9017422,
+ 0x91008261,
+ 0xb8606822,
+ 0x8b000283,
+ 0xb900c062,
+ 0x91001000,
+ 0xf102301f,
+ 0x54ffff61,
+ 0xb9400a60,
+ 0xb9000280,
+ 0xb9400e60,
+ 0xb9005280,
+ 0xb9401260,
+ 0xb9007e80,
+ 0xb9401660,
+ 0xb9008280,
+ 0xb9401a60,
+ 0xb9008680,
+ 0xb940ae60,
+ 0xb9024280,
+ 0xb940b260,
+ 0xb9024680,
+ 0xb940b660,
+ 0xb9024a80,
+ 0xb940ba60,
+ 0xb9024e80,
+ 0xb940be60,
+ 0xb9025280,
+ 0xb940c260,
+ 0xb9025680,
+ 0xb940c660,
+ 0xb9025a80,
+ 0xb940ca60,
+ 0xb9026280,
+ 0xb940ce60,
+ 0xb9026680,
+ 0xb940d260,
+ 0xb9027280,
+ 0xb940d660,
+ 0xb9027680,
+ 0xb940da60,
+ 0xb9027a80,
+ 0xb940de60,
+ 0xb9027e80,
+ 0xb940e260,
+ 0xb9028280,
+ 0xb940e660,
+ 0xb9028680,
+ 0xb940ea60,
+ 0xb9028a80,
+ 0xb940ee60,
+ 0xb9029280,
+ 0xb940f260,
+ 0xb9029680,
+ 0xb940f660,
+ 0xb9029a80,
+ 0xb940fa60,
+ 0xb902c680,
+ 0xb940fe60,
+ 0xb902ca80,
+ 0xb9410260,
+ 0xb902d280,
+ 0xb9410660,
+ 0xb902d680,
+ 0xb9410a60,
+ 0xb902da80,
+ 0xb9410e60,
+ 0xb902f280,
+ 0xb9422260,
+ 0x3100041f,
+ 0x540000c0,
+ 0xb9422661,
+ 0x53007c00,
+ 0xb9000001,
+ 0x52800020,
+ 0x97fffe65,
+ 0x52800020,
+ 0xb9004680,
+ 0xb9404a80,
+ 0x3607ffe0,
+ 0xb941ae60,
+ 0xb9000aa0,
+ 0xb941b260,
+ 0xb9000ea0,
+ 0xb941b660,
+ 0xb90012a0,
+ 0xb941ba60,
+ 0xb90016a0,
+ 0xb941be60,
+ 0xb9003aa0,
+ 0xb941c260,
+ 0xb9003ea0,
+ 0xb9422260,
+ 0x3100041f,
+ 0x54000080,
+ 0x53007c00,
+ 0x320083e1,
+ 0xb9000001,
+ 0xaa1403e0,
+ 0x97fffe84,
+ 0xb9421a60,
+ 0x3100041f,
+ 0x54000100,
+ 0x53007c00,
+ 0xb9421e61,
+ 0xb9400002,
+ 0x2a010041,
+ 0xb9000001,
+ 0x52800020,
+ 0x97fffe43,
+ 0xaa1403e0,
+ 0x97fffea0,
+ 0xb9422260,
+ 0x3100041f,
+ 0x54000080,
+ 0x53007c00,
+ 0x52a00021,
+ 0xb9000001,
+ 0xf94007f3,
+ 0xa94157f4,
+ 0xa9425ff6,
+ 0xa9437bfd,
+ 0x910103ff,
+ 0xd65f03c0,
diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.c b/plat/rockchip/rk3368/drivers/pmu/pmu.c
new file mode 100644
index 0000000..fc31413
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/pmu/pmu.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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 <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3368_def.h>
+#include <pmu_sram.h>
+#include <soc.h>
+#include <pmu.h>
+#include <ddr_rk3368.h>
+#include <pmu_com.h>
+
+static struct psram_data_t *psram_sleep_cfg =
+ (struct psram_data_t *)PSRAM_DT_BASE;
+
+void rk3368_flash_l2_b(void)
+{
+ uint32_t wait_cnt = 0;
+
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b);
+ dsb();
+
+ while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)
+ & BIT(clst_b_l2_flsh_done))) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ WARN("%s:reg %x,wait\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST));
+ }
+
+ regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b);
+}
+
+static inline int rk3368_pmu_bus_idle(uint32_t req, uint32_t idle)
+{
+ uint32_t mask = BIT(req);
+ uint32_t idle_mask = 0;
+ uint32_t idle_target = 0;
+ uint32_t val;
+ uint32_t wait_cnt = 0;
+
+ switch (req) {
+ case bus_ide_req_clst_l:
+ idle_mask = BIT(pmu_idle_ack_cluster_l);
+ idle_target = (idle << pmu_idle_ack_cluster_l);
+ break;
+
+ case bus_ide_req_clst_b:
+ idle_mask = BIT(pmu_idle_ack_cluster_b);
+ idle_target = (idle << pmu_idle_ack_cluster_b);
+ break;
+
+ case bus_ide_req_cxcs:
+ idle_mask = BIT(pmu_idle_ack_cxcs);
+ idle_target = ((!idle) << pmu_idle_ack_cxcs);
+ break;
+
+ case bus_ide_req_cci400:
+ idle_mask = BIT(pmu_idle_ack_cci400);
+ idle_target = ((!idle) << pmu_idle_ack_cci400);
+ break;
+
+ case bus_ide_req_gpu:
+ idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu);
+ idle_target = (idle << pmu_idle_ack_gpu) |
+ (idle << pmu_idle_gpu);
+ break;
+
+ case bus_ide_req_core:
+ idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core);
+ idle_target = (idle << pmu_idle_ack_core) |
+ (idle << pmu_idle_core);
+ break;
+
+ case bus_ide_req_bus:
+ idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus);
+ idle_target = (idle << pmu_idle_ack_bus) |
+ (idle << pmu_idle_bus);
+ break;
+ case bus_ide_req_dma:
+ idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma);
+ idle_target = (idle << pmu_idle_ack_dma) |
+ (idle << pmu_idle_dma);
+ break;
+
+ case bus_ide_req_peri:
+ idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri);
+ idle_target = (idle << pmu_idle_ack_peri) |
+ (idle << pmu_idle_peri);
+ break;
+
+ case bus_ide_req_video:
+ idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video);
+ idle_target = (idle << pmu_idle_ack_video) |
+ (idle << pmu_idle_video);
+ break;
+
+ case bus_ide_req_vio:
+ idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio);
+ idle_target = (pmu_idle_ack_vio) |
+ (idle << pmu_idle_vio);
+ break;
+
+ case bus_ide_req_alive:
+ idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive);
+ idle_target = (idle << pmu_idle_ack_alive) |
+ (idle << pmu_idle_alive);
+ break;
+
+ case bus_ide_req_pmu:
+ idle_mask = BIT(pmu_idle_ack_pmu) | BIT(pmu_idle_pmu);
+ idle_target = (idle << pmu_idle_ack_pmu) |
+ (idle << pmu_idle_pmu);
+ break;
+
+ case bus_ide_req_msch:
+ idle_mask = BIT(pmu_idle_ack_msch) | BIT(pmu_idle_msch);
+ idle_target = (idle << pmu_idle_ack_msch) |
+ (idle << pmu_idle_msch);
+ break;
+
+ case bus_ide_req_cci:
+ idle_mask = BIT(pmu_idle_ack_cci) | BIT(pmu_idle_cci);
+ idle_target = (idle << pmu_idle_ack_cci) |
+ (idle << pmu_idle_cci);
+ break;
+
+ default:
+ ERROR("%s: Unsupported the idle request\n", __func__);
+ break;
+ }
+
+ val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ);
+ if (idle)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val);
+
+ while ((mmio_read_32(PMU_BASE +
+ PMU_BUS_IDE_ST) & idle_mask) != idle_target) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ WARN("%s:st=%x(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST),
+ idle_mask);
+ }
+
+ return 0;
+}
+
+void pmu_scu_b_pwrup(void)
+{
+ regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b);
+ rk3368_pmu_bus_idle(bus_ide_req_clst_b, 0);
+}
+
+static void pmu_scu_b_pwrdn(void)
+{
+ uint32_t wait_cnt = 0;
+
+ if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) &
+ PM_PWRDM_CPUSB_MSK) != PM_PWRDM_CPUSB_MSK) {
+ ERROR("%s: not all cpus is off\n", __func__);
+ return;
+ }
+
+ rk3368_flash_l2_b();
+
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b);
+
+ while (!(mmio_read_32(PMU_BASE +
+ PMU_CORE_PWR_ST) & BIT(clst_b_l2_wfi))) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ ERROR("%s:wait cluster-b l2(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST));
+ }
+ rk3368_pmu_bus_idle(bus_ide_req_clst_b, 1);
+}
+
+static void pmu_sleep_mode_config(void)
+{
+ uint32_t pwrmd_core, pwrmd_com;
+
+ pwrmd_core = BIT(pmu_mdcr_cpu0_pd) |
+ BIT(pmu_mdcr_scu_l_pd) |
+ BIT(pmu_mdcr_l2_flush) |
+ BIT(pmu_mdcr_l2_idle) |
+ BIT(pmu_mdcr_clr_clst_l) |
+ BIT(pmu_mdcr_clr_core) |
+ BIT(pmu_mdcr_clr_cci) |
+ BIT(pmu_mdcr_core_pd);
+
+ pwrmd_com = BIT(pmu_mode_en) |
+ BIT(pmu_mode_sref_enter) |
+ BIT(pmu_mode_pwr_off);
+
+ regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_l_wkup_en);
+ regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_b_wkup_en);
+ regs_updata_bit_clr(PMU_BASE + PMU_WKUP_CFG2, pmu_gpio_wkup_en);
+
+ mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(2));
+ mmio_write_32(PMU_BASE + PMU_PLLRST_CNT, CYCL_24M_CNT_US(100));
+ mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(2));
+ mmio_write_32(PMU_BASE + PMU_PWRMD_CORE, pwrmd_core);
+ mmio_write_32(PMU_BASE + PMU_PWRMD_COM, pwrmd_com);
+ dsb();
+}
+
+static void ddr_suspend_save(void)
+{
+ ddr_reg_save(1, psram_sleep_cfg->ddr_data);
+}
+
+static void pmu_set_sleep_mode(void)
+{
+ ddr_suspend_save();
+ pmu_sleep_mode_config();
+ soc_sleep_config();
+ regs_updata_bit_set(PMU_BASE + PMU_PWRMD_CORE, pmu_mdcr_global_int_dis);
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_glbl_int_dis_b);
+ pmu_scu_b_pwrdn();
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+}
+
+void plat_rockchip_pmusram_prepare(void)
+{
+ uint32_t *sram_dst, *sram_src;
+ size_t sram_size = 2;
+ uint32_t code_size, data_size;
+
+ /* pmu sram code and data prepare */
+ sram_dst = (uint32_t *)PMUSRAM_BASE;
+ sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start;
+ sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end -
+ (uint32_t *)sram_src;
+ u32_align_cpy(sram_dst, sram_src, sram_size);
+
+ /* ddr code */
+ sram_dst += sram_size;
+ sram_src = ddr_get_resume_code_base();
+ code_size = ddr_get_resume_code_size();
+ u32_align_cpy(sram_dst, sram_src, code_size / 4);
+ psram_sleep_cfg->ddr_func = (uint64_t)sram_dst;
+
+ /* ddr data */
+ sram_dst += (code_size / 4);
+ data_size = ddr_get_resume_data_size();
+ psram_sleep_cfg->ddr_data = (uint64_t)sram_dst;
+
+ assert((uint64_t)(sram_dst + data_size / 4) < PSRAM_SP_BOTTOM);
+ psram_sleep_cfg->sp = PSRAM_SP_TOP;
+}
+
+static int cpus_id_power_domain(uint32_t cluster,
+ uint32_t cpu,
+ uint32_t pd_state,
+ uint32_t wfie_msk)
+{
+ uint32_t pd;
+ uint64_t mpidr;
+
+ if (cluster)
+ pd = PD_CPUB0 + cpu;
+ else
+ pd = PD_CPUL0 + cpu;
+
+ if (pmu_power_domain_st(pd) == pd_state)
+ return 0;
+
+ if (pd_state == pmu_pd_off) {
+ mpidr = (cluster << MPIDR_AFF1_SHIFT) | cpu;
+ if (check_cpu_wfie(mpidr, wfie_msk))
+ return -EINVAL;
+ }
+
+ return pmu_power_domain_ctr(pd, pd_state);
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, boot_cluster, cpu;
+
+ boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
+ boot_cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CLUSTER0_CORE_COUNT; cpu++) {
+ if (!boot_cluster && (cpu == boot_cpu))
+ continue;
+ cpus_id_power_domain(0, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+ }
+
+ for (cpu = 0; cpu < PLATFORM_CLUSTER1_CORE_COUNT; cpu++) {
+ if (boot_cluster && (cpu == boot_cpu))
+ continue;
+ cpus_id_power_domain(1, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+ }
+}
+
+static int cores_pwr_domain_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu, cluster;
+ uint32_t cpuon_id;
+
+ cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ cluster = MPIDR_AFFLVL1_VAL(mpidr);
+
+ /* Make sure the cpu is off,Before power up the cpu! */
+ cpus_id_power_domain(cluster, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+
+ cpuon_id = (cluster * PLATFORM_CLUSTER0_CORE_COUNT) + cpu;
+ assert(cpuson_flags[cpuon_id] == 0);
+ cpuson_flags[cpuon_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpuon_id] = entrypoint;
+
+ /* Switch boot addr to pmusram */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ dsb();
+
+ cpus_id_power_domain(cluster, cpu, pmu_pd_on, CKECK_WFEI_MSK);
+
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster),
+ (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ return 0;
+}
+
+static int cores_pwr_domain_on_finish(void)
+{
+ uint32_t cpuon_id;
+
+ cpuon_id = plat_my_core_pos();
+ assert(cpuson_flags[cpuon_id] == 0);
+ cpuson_flags[cpuon_id] = 0x00;
+
+ return 0;
+}
+
+static int sys_pwr_domain_resume(void)
+{
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+
+ pm_plls_resume();
+ pmu_scu_b_pwrup();
+
+ return 0;
+}
+
+static int sys_pwr_domain_suspend(void)
+{
+ nonboot_cpus_off();
+ pmu_set_sleep_mode();
+
+ psram_sleep_cfg->sys_mode = PMU_SYS_SLP_MODE;
+ psram_sleep_cfg->ddr_flag = 0;
+
+ return 0;
+}
+
+static struct rockchip_pm_ops_cb pm_ops = {
+ .cores_pwr_dm_on = cores_pwr_domain_on,
+ .cores_pwr_dm_on_finish = cores_pwr_domain_on_finish,
+ .sys_pwr_dm_suspend = sys_pwr_domain_suspend,
+ .sys_pwr_dm_resume = sys_pwr_domain_resume,
+ .sys_gbl_soft_reset = soc_sys_global_soft_reset,
+};
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ plat_setup_rockchip_pm_ops(&pm_ops);
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+
+ psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
+
+ nonboot_cpus_off();
+ INFO("%s(%d): pd status %x\n", __func__, __LINE__,
+ mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.h b/plat/rockchip/rk3368/drivers/pmu/pmu.h
new file mode 100644
index 0000000..2cf60fd
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/pmu/pmu.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+
+#ifndef __PMU_H__
+#define __PMU_H__
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE 0x80
+#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WKUP_CFG0 0x0
+#define PMU_WKUP_CFG1 0x4
+#define PMU_WKUP_CFG2 0x8
+#define PMU_TIMEOUT_CNT 0x7c
+#define PMU_PWRDN_CON 0xc
+#define PMU_PWRDN_ST 0x10
+#define PMU_CORE_PWR_ST 0x38
+
+#define PMU_PWRMD_CORE 0x14
+#define PMU_PWRMD_COM 0x18
+#define PMU_SFT_CON 0x1c
+#define PMU_BUS_IDE_REQ 0x3c
+#define PMU_BUS_IDE_ST 0x40
+#define PMU_OSC_CNT 0x48
+#define PMU_PLLLOCK_CNT 0x4c
+#define PMU_PLLRST_CNT 0x50
+#define PMU_STABLE_CNT 0x54
+#define PMU_DDRIO_PWR_CNT 0x58
+#define PMU_WKUPRST_CNT 0x5c
+
+enum pmu_powermode_core {
+ pmu_mdcr_global_int_dis = 0,
+ pmu_mdcr_core_src_gt,
+ pmu_mdcr_clr_cci,
+ pmu_mdcr_cpu0_pd,
+ pmu_mdcr_clr_clst_l = 4,
+ pmu_mdcr_clr_core,
+ pmu_mdcr_scu_l_pd,
+ pmu_mdcr_core_pd,
+ pmu_mdcr_l2_idle = 8,
+ pmu_mdcr_l2_flush
+};
+
+/*
+ * the shift of bits for cores status
+ */
+enum pmu_core_pwrst_shift {
+ clstl_cpu_wfe = 2,
+ clstl_cpu_wfi = 6,
+ clstb_cpu_wfe = 12,
+ clstb_cpu_wfi = 16
+};
+
+enum pmu_pdid {
+ PD_CPUL0 = 0,
+ PD_CPUL1,
+ PD_CPUL2,
+ PD_CPUL3,
+ PD_SCUL,
+ PD_CPUB0 = 5,
+ PD_CPUB1,
+ PD_CPUB2,
+ PD_CPUB3,
+ PD_SCUB = 9,
+ PD_PERI = 13,
+ PD_VIDEO,
+ PD_VIO,
+ PD_GPU0,
+ PD_GPU1,
+ PD_END
+};
+
+enum pmu_bus_ide {
+ bus_ide_req_clst_l = 0,
+ bus_ide_req_clst_b,
+ bus_ide_req_gpu,
+ bus_ide_req_core,
+ bus_ide_req_bus = 4,
+ bus_ide_req_dma,
+ bus_ide_req_peri,
+ bus_ide_req_video,
+ bus_ide_req_vio = 8,
+ bus_ide_req_res0,
+ bus_ide_req_cxcs,
+ bus_ide_req_alive,
+ bus_ide_req_pmu = 12,
+ bus_ide_req_msch,
+ bus_ide_req_cci,
+ bus_ide_req_cci400 = 15,
+ bus_ide_req_end
+};
+
+enum pmu_powermode_common {
+ pmu_mode_en = 0,
+ pmu_mode_res0,
+ pmu_mode_bus_pd,
+ pmu_mode_wkup_rst,
+ pmu_mode_pll_pd = 4,
+ pmu_mode_pwr_off,
+ pmu_mode_pmu_use_if,
+ pmu_mode_pmu_alive_use_if,
+ pmu_mode_osc_dis = 8,
+ pmu_mode_input_clamp,
+ pmu_mode_sref_enter,
+ pmu_mode_ddrc_gt,
+ pmu_mode_ddrio_ret = 12,
+ pmu_mode_ddrio_ret_deq,
+ pmu_mode_clr_pmu,
+ pmu_mode_clr_alive,
+ pmu_mode_clr_bus = 16,
+ pmu_mode_clr_dma,
+ pmu_mode_clr_msch,
+ pmu_mode_clr_peri,
+ pmu_mode_clr_video = 20,
+ pmu_mode_clr_vio,
+ pmu_mode_clr_gpu,
+ pmu_mode_clr_mcu,
+ pmu_mode_clr_cxcs = 24,
+ pmu_mode_clr_cci400,
+ pmu_mode_res1,
+ pmu_mode_res2,
+ pmu_mode_res3 = 28,
+ pmu_mode_mclst
+};
+
+enum pmu_core_power_st {
+ clst_l_cpu_wfe = 2,
+ clst_l_cpu_wfi = 6,
+ clst_b_l2_flsh_done = 10,
+ clst_b_l2_wfi = 11,
+ clst_b_cpu_wfe = 12,
+ clst_b_cpu_wfi = 16,
+ mcu_sleeping = 20,
+};
+
+enum pmu_sft_con {
+ pmu_sft_acinactm_clst_b = 5,
+ pmu_sft_l2flsh_clst_b,
+ pmu_sft_glbl_int_dis_b = 9,
+ pmu_sft_ddrio_ret_cfg = 11,
+};
+
+enum pmu_wkup_cfg2 {
+ pmu_cluster_l_wkup_en = 0,
+ pmu_cluster_b_wkup_en,
+ pmu_gpio_wkup_en,
+ pmu_sdio_wkup_en,
+ pmu_sdmmc_wkup_en,
+ pmu_sim_wkup_en,
+ pmu_timer_wkup_en,
+ pmu_usbdev_wkup_en,
+ pmu_sft_wkup_en,
+ pmu_wdt_mcu_wkup_en,
+ pmu_timeout_wkup_en,
+};
+
+enum pmu_bus_idle_st {
+ pmu_idle_ack_cluster_l = 0,
+ pmu_idle_ack_cluster_b,
+ pmu_idle_ack_gpu,
+ pmu_idle_ack_core,
+ pmu_idle_ack_bus,
+ pmu_idle_ack_dma,
+ pmu_idle_ack_peri,
+ pmu_idle_ack_video,
+ pmu_idle_ack_vio,
+ pmu_idle_ack_cci = 10,
+ pmu_idle_ack_msch,
+ pmu_idle_ack_alive,
+ pmu_idle_ack_pmu,
+ pmu_idle_ack_cxcs,
+ pmu_idle_ack_cci400,
+ pmu_inactive_cluster_l,
+ pmu_inactive_cluster_b,
+ pmu_idle_gpu,
+ pmu_idle_core,
+ pmu_idle_bus,
+ pmu_idle_dma,
+ pmu_idle_peri,
+ pmu_idle_video,
+ pmu_idle_vio,
+ pmu_idle_cci = 26,
+ pmu_idle_msch,
+ pmu_idle_alive,
+ pmu_idle_pmu,
+ pmu_active_cxcs,
+ pmu_active_cci,
+};
+
+#define PM_PWRDM_CPUSB_MSK (0xf << 5)
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+#define PD_CTR_LOOP 500
+#define CHK_CPU_LOOP 500
+
+#define MAX_WAIT_CONUT 1000
+
+#endif /* __PMU_H__ */
diff --git a/plat/rockchip/rk3368/drivers/soc/soc.c b/plat/rockchip/rk3368/drivers/soc/soc.c
new file mode 100644
index 0000000..3630828
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/soc/soc.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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 <arch_helpers.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3368_def.h>
+#include <soc.h>
+
+static uint32_t plls_con[END_PLL_ID][4];
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(CCI400_BASE, CCI400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART_DBG_BASE, UART_DBG_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PCTL_BASE, DDR_PCTL_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PHY_BASE, DDR_PHY_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GRF_BASE, GRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SISE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT1, 0xffffffff);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void sgrf_init(void)
+{
+ /* setting all configurable ip into no-secure */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SOC_CON7_BITS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SOC_CON_NS);
+
+ /* secure dma to no sesure */
+ mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(0), SGRF_BUSDMAC_CON0_NS);
+ mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), SGRF_BUSDMAC_CON1_NS);
+ dsb();
+
+ /* rst dma1 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1),
+ RST_DMA1_MSK | (RST_DMA1_MSK << 16));
+ /* rst dma2 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4),
+ RST_DMA2_MSK | (RST_DMA2_MSK << 16));
+
+ dsb();
+
+ /* release dma1 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16));
+ /* release dma2 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16));
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ sgrf_init();
+}
+
+void regs_updata_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift)
+{
+ uint32_t tmp, orig;
+
+ orig = mmio_read_32(addr);
+
+ tmp = orig & ~(mask << shift);
+ tmp |= (val & mask) << shift;
+
+ if (tmp != orig)
+ mmio_write_32(addr, tmp);
+ dsb();
+}
+
+static void plls_suspend(uint32_t pll_id)
+{
+ plls_con[pll_id][0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0));
+ plls_con[pll_id][1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1));
+ plls_con[pll_id][2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2));
+ plls_con[pll_id][3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3));
+
+ mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_BYPASS);
+}
+
+static void pm_plls_suspend(void)
+{
+ plls_suspend(NPLL_ID);
+ plls_suspend(CPLL_ID);
+ plls_suspend(GPLL_ID);
+ plls_suspend(ABPLL_ID);
+ plls_suspend(ALPLL_ID);
+}
+
+static inline void plls_resume(void)
+{
+ mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3),
+ plls_con[ABPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3),
+ plls_con[ALPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3),
+ plls_con[GPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3),
+ plls_con[CPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3),
+ plls_con[NPLL_ID][3] | PLL_BYPASS_W_MSK);
+}
+
+void soc_sleep_config(void)
+{
+ int i = 0;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000);
+ pm_plls_suspend();
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000);
+}
+
+void pm_plls_resume(void)
+{
+ plls_resume();
+
+ mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3),
+ plls_con[ABPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3),
+ plls_con[ALPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3),
+ plls_con[GPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3),
+ plls_con[CPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3),
+ plls_con[NPLL_ID][3] | PLLS_MODE_WMASK);
+}
+
+void __dead2 soc_sys_global_soft_reset(void)
+{
+ uint32_t temp_val;
+
+ mmio_write_32(CRU_BASE + PLL_CONS((GPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((CPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((NPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((ABPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((ALPLL_ID), 3), PLL_SLOW_BITS);
+
+ temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON) |
+ PMU_RST_BY_SECOND_SFT;
+
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
diff --git a/plat/rockchip/rk3368/drivers/soc/soc.h b/plat/rockchip/rk3368/drivers/soc/soc.h
new file mode 100644
index 0000000..6e2c3fe
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/soc/soc.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+
+#ifndef __SOC_H__
+#define __SOC_H__
+
+enum plls_id {
+ ABPLL_ID = 0,
+ ALPLL_ID,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ NPLL_ID,
+ END_PLL_ID,
+};
+
+/*****************************************************************************
+ * secure timer
+ *****************************************************************************/
+#define TIMER_LOADE_COUNT0 0x00
+#define TIMER_LOADE_COUNT1 0x04
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INTSTATUS 0x18
+
+#define TIMER_EN 0x1
+
+#define STIMER1_BASE (STIME_BASE + 0x20)
+
+#define CYCL_24M_CNT_US(us) (24 * us)
+#define CYCL_24M_CNT_MS(ms) (ms * CYCL_24M_CNT_US(1000))
+
+/*****************************************************************************
+ * sgrf reg, offset
+ *****************************************************************************/
+#define SGRF_SOC_CON(n) (0x0 + (n) * 4)
+#define SGRF_BUSDMAC_CON(n) (0x100 + (n) * 4)
+
+#define SGRF_SOC_CON_NS 0xffff0000
+
+/*****************************************************************************
+ * con6[2]pmusram is security.
+ * con6[6]stimer is security.
+ *****************************************************************************/
+#define PMUSRAM_S_SHIFT 2
+#define PMUSRAM_S 1
+#define STIMER_S_SHIFT 6
+#define STIMER_S 1
+#define SGRF_SOC_CON7_BITS ((0xffff << 16) | \
+ (PMUSRAM_S << PMUSRAM_S_SHIFT) | \
+ (STIMER_S << STIMER_S_SHIFT))
+
+#define SGRF_BUSDMAC_CON0_NS 0xfffcfff8
+#define SGRF_BUSDMAC_CON1_NS 0xffff0fff
+
+/*
+ * sgrf_soc_con1~2, mask and offset
+ */
+#define CPU_BOOT_ADDR_WMASK 0xffff0000
+#define CPU_BOOT_ADDR_ALIGN 16
+
+/*****************************************************************************
+ * cru reg, offset
+ *****************************************************************************/
+#define CRU_SOFTRST_CON 0x300
+#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4))
+#define CRU_SOFTRSTS_CON_CNT 15
+
+#define SOFTRST_DMA1 0x40004
+#define SOFTRST_DMA2 0x10001
+
+#define RST_DMA1_MSK 0x4
+#define RST_DMA2_MSK 0x0
+
+#define CRU_CLKSEL_CON 0x100
+#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4))
+#define CRU_CLKSEL_CON_CNT 56
+
+#define CRU_CLKGATE_CON 0x200
+#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4))
+#define CRU_CLKGATES_CON_CNT 25
+
+#define CRU_GLB_SRST_FST 0x280
+#define CRU_GLB_SRST_SND 0x284
+#define CRU_GLB_RST_CON 0x388
+
+#define CRU_CONS_GATEID(i) (16 * (i))
+#define GATE_ID(reg, bit) ((reg * 16) + bit)
+
+#define PMU_RST_BY_SECOND_SFT (BIT(1) << 2)
+#define PMU_RST_NOT_BY_SFT (BIT(1) << 2)
+
+/***************************************************************************
+ * pll
+ ***************************************************************************/
+#define PLL_PWR_DN_MSK (0x1 << 1)
+#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1)
+#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1)
+#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1)
+#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1)
+#define PLL_BYPASS_MSK (0x1 << 0)
+#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16)
+#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1)
+#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1)
+#define PLL_MODE_SHIFT 8
+#define PLL_MODE_MSK 0x3
+#define PLLS_MODE_WMASK (PLL_MODE_MSK << (16 + PLL_MODE_SHIFT))
+#define PLL_SLOW 0x0
+#define PLL_NORM 0x1
+#define PLL_DEEP 0x2
+#define PLL_SLOW_BITS REG_WMSK_BITS(PLL_SLOW, 8, 0x3)
+#define PLL_NORM_BITS REG_WMSK_BITS(PLL_NORM, 8, 0x3)
+#define PLL_DEEP_BITS REG_WMSK_BITS(PLL_DEEP, 8, 0x3)
+
+#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
+
+#define REG_W_MSK(bits_shift, msk) \
+ ((msk) << ((bits_shift) + 16))
+#define REG_VAL_CLRBITS(val, bits_shift, msk) \
+ (val & (~(msk << bits_shift)))
+#define REG_SET_BITS(bits, bits_shift, msk) \
+ (((bits) & (msk)) << (bits_shift))
+#define REG_WMSK_BITS(bits, bits_shift, msk) \
+ (REG_W_MSK(bits_shift, msk) | \
+ REG_SET_BITS(bits, bits_shift, msk))
+
+#define regs_updata_bit_set(addr, shift) \
+ regs_updata_bits((addr), 0x1, 0x1, (shift))
+#define regs_updata_bit_clr(addr, shift) \
+ regs_updata_bits((addr), 0x0, 0x1, (shift))
+
+void __dead2 soc_sys_global_soft_reset(void);
+void regs_updata_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift);
+void soc_sleep_config(void);
+void pm_plls_resume(void);
+
+#endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3368/include/platform_def.h b/plat/rockchip/rk3368/include/platform_def.h
new file mode 100644
index 0000000..876cbfb
--- /dev/null
+++ b/plat/rockchip/rk3368/include/platform_def.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014-2016, 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.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <rk3368_def.h>
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CLUSTER_COUNT 2
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 4
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF txet, ro, rw, Size: 512KB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x80000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x8000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE RK3368_GICD_BASE
+#define PLAT_RK_GICC_BASE RK3368_GICC_BASE
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_RK_G1S_IRQS RK_G1S_IRQS
+
+#define PLAT_RK_UART_BASE RK3368_UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3368_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3368_BAUDRATE
+
+#define PLAT_RK_CCI_BASE CCI400_BASE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define RK_PLAT_AARCH_CFG RK_PLAT_CFG0
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
new file mode 100644
index 0000000..4fadf21
--- /dev/null
+++ b/plat/rockchip/rk3368/platform.mk
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2016, 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.
+#
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/pmusram \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/drivers/ddr/ \
+ -I${RK_PLAT_SOC}/include/
+
+RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c \
+ ${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
+ plat/common/aarch64/plat_common.c \
+ plat/common/aarch64/plat_psci_common.c
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/console/console.S \
+ drivers/ti/uart/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \
+ ${RK_PLAT_COMMON}/plat_delay_timer.c \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
+ ${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \
+
+ENABLE_PLAT_COMPAT := 0
diff --git a/plat/rockchip/rk3368/rk3368_def.h b/plat/rockchip/rk3368/rk3368_def.h
new file mode 100644
index 0000000..614f270
--- /dev/null
+++ b/plat/rockchip/rk3368/rk3368_def.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#ifndef __PLAT_DEF_H__
+#define __PLAT_DEF_H__
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define CCI400_BASE 0xffb90000
+#define CCI400_SIZE 0x10000
+
+#define GIC400_BASE 0xffb70000
+#define GIC400_SIZE 0x10000
+
+#define STIME_BASE 0xff830000
+#define STIME_SIZE 0x10000
+
+#define CRU_BASE 0xff760000
+#define CRU_SIZE 0x10000
+
+#define GRF_BASE 0xff770000
+#define GRF_SIZE 0x10000
+
+#define SGRF_BASE 0xff740000
+#define SGRF_SIZE 0x10000
+
+#define PMU_BASE 0xff730000
+#define PMU_GRF_BASE 0xff738000
+#define PMU_SIZE 0x10000
+
+#define RK_INTMEM_BASE 0xff8c0000
+#define RK_INTMEM_SIZE 0x10000
+
+#define UART_DBG_BASE 0xff690000
+#define UART_DBG_SIZE 0x10000
+
+#define CRU_BASE 0xff760000
+
+#define PMUSRAM_BASE 0xff720000
+#define PMUSRAM_SIZE 0x10000
+#define PMUSRAM_RSIZE 0x1000
+
+#define DDR_PCTL_BASE 0xff610000
+#define DDR_PCTL_SIZE 0x10000
+
+#define DDR_PHY_BASE 0xff620000
+#define DDR_PHY_SIZE 0x10000
+
+#define SERVICE_BUS_BASE 0xffac0000
+#define SERVICE_BUS_SISE 0x50000
+
+#define COLD_BOOT_BASE 0xffff0000
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3368_UART2_BASE UART_DBG_BASE
+#define RK3368_BAUDRATE 115200
+#define RK3368_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+#define SYS_COUNTER_FREQ_IN_MHZ 24
+
+/******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define RK3368_GICD_BASE (GIC400_BASE + 0x1000)
+#define RK3368_GICC_BASE (GIC400_BASE + 0x2000)
+#define RK3368_GICR_BASE 0 /* no GICR in GIC-400 */
+
+/*****************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 3
+#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 4
+
+/******************************************************************************
+ * cpu up status
+ ******************************************************************************/
+#define PMU_CPU_HOTPLUG 0xdeadbeaf
+#define PMU_CPU_AUTO_PWRDN 0xabcdef12
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER 29
+
+#define RK_IRQ_SEC_SGI_0 8
+#define RK_IRQ_SEC_SGI_1 9
+#define RK_IRQ_SEC_SGI_2 10
+#define RK_IRQ_SEC_SGI_3 11
+#define RK_IRQ_SEC_SGI_4 12
+#define RK_IRQ_SEC_SGI_5 13
+#define RK_IRQ_SEC_SGI_6 14
+#define RK_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 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 RK_G1S_IRQS (RK_IRQ_SEC_PHY_TIMER)
+
+#endif /* __PLAT_DEF_H__ */
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
new file mode 100644
index 0000000..351de7d
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2016, 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 <arch_helpers.h>
+#include <assert.h>
+#include <bakery_lock.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3399_def.h>
+#include <pmu_sram.h>
+#include <soc.h>
+#include <pmu.h>
+#include <pmu_com.h>
+
+static struct psram_data_t *psram_sleep_cfg =
+ (struct psram_data_t *)PSRAM_DT_BASE;
+
+/*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg,
+ * it is core_pwr_pd mode
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode
+ * so we need core_pm_cfg_info to distinguish which method be used now.
+ */
+
+static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT]
+#if USE_COHERENT_MEM
+__attribute__ ((section("tzfw_coherent_mem")))
+#endif
+;/* coheront */
+
+void plat_rockchip_pmusram_prepare(void)
+{
+ uint32_t *sram_dst, *sram_src;
+ size_t sram_size = 2;
+
+ /*
+ * pmu sram code and data prepare
+ */
+ sram_dst = (uint32_t *)PMUSRAM_BASE;
+ sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start;
+ sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end -
+ (uint32_t *)sram_src;
+
+ u32_align_cpy(sram_dst, sram_src, sram_size);
+
+ psram_sleep_cfg->sp = PSRAM_DT_BASE;
+}
+
+static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id)
+{
+ return core_pm_cfg_info[cpu_id];
+}
+
+static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value)
+{
+ core_pm_cfg_info[cpu_id] = value;
+#if !USE_COHERENT_MEM
+ flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id],
+ sizeof(uint32_t));
+#endif
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ uint32_t cfg_info;
+ uint32_t cpu_pd = PD_CPUL0 + cpu_id;
+ /*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically.
+ */
+
+ cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id);
+
+ if (cfg_info == core_pwr_pd) {
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ CORES_PM_DISABLE);
+ /* if the cores have be on, power off it firstly */
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ }
+
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
+ } else {
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id);
+ return -EINVAL;
+ }
+
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ BIT(core_pm_sft_wakeup_en));
+ }
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
+{
+ uint32_t cpu_pd;
+ uint32_t core_pm_value;
+
+ cpu_pd = PD_CPUL0 + cpu_id;
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
+ return 0;
+
+ if (pd_cfg == core_pwr_pd) {
+ if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
+ return -EINVAL;
+
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ CORES_PM_DISABLE);
+
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ } else {
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+
+ core_pm_value = BIT(core_pm_en);
+ if (pd_cfg == core_pwr_wfi_int)
+ core_pm_value |= BIT(core_pm_int_wakeup_en);
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ core_pm_value);
+ }
+
+ return 0;
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu;
+
+ boot_cpu = plat_my_core_pos();
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ if (cpu == boot_cpu)
+ continue;
+ cpus_power_domain_off(cpu, core_pwr_pd);
+ }
+}
+
+static int cores_pwr_domain_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpu_id] = entrypoint;
+ dsb();
+
+ cpus_power_domain_on(cpu_id);
+
+ return 0;
+}
+
+static int cores_pwr_domain_off(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi);
+
+ return 0;
+}
+
+static int cores_pwr_domain_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
+ cpuson_entry_point[cpu_id] = (uintptr_t)psci_entrypoint;
+ dsb();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
+
+ return 0;
+}
+
+static int cores_pwr_domain_on_finish(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpuson_flags[cpu_id] = 0;
+ cpuson_entry_point[cpu_id] = 0;
+
+ /* Disable core_pm */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE);
+
+ return 0;
+}
+
+static int cores_pwr_domain_resume(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpuson_flags[cpu_id] = 0;
+ cpuson_entry_point[cpu_id] = 0;
+
+ /* Disable core_pm */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE);
+
+ return 0;
+}
+
+static void sys_slp_config(void)
+{
+ uint32_t slp_mode_cfg = 0;
+
+ slp_mode_cfg = PMU_PWR_MODE_EN |
+ PMU_CPU0_PD_EN |
+ PMU_L2_FLUSH_EN |
+ PMU_L2_IDLE_EN |
+ PMU_SCU_PD_EN |
+ PMU_CLK_CORE_SRC_GATE_EN;
+ mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_L_WKUP_EN);
+ mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_B_WKUP_EN);
+ mmio_clrbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_GPIO_WKUP_EN);
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg);
+}
+
+static int sys_pwr_domain_suspend(void)
+{
+ sys_slp_config();
+ plls_suspend();
+ psram_sleep_cfg->sys_mode = PMU_SYS_SLP_MODE;
+ pmu_sgrf_rst_hld();
+ return 0;
+}
+
+static int sys_pwr_domain_resume(void)
+{
+ pmu_sgrf_rst_hld_release();
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+ plls_resume();
+
+ return 0;
+}
+
+static struct rockchip_pm_ops_cb pm_ops = {
+ .cores_pwr_dm_on = cores_pwr_domain_on,
+ .cores_pwr_dm_off = cores_pwr_domain_off,
+ .cores_pwr_dm_on_finish = cores_pwr_domain_on_finish,
+ .cores_pwr_dm_suspend = cores_pwr_domain_suspend,
+ .cores_pwr_dm_resume = cores_pwr_domain_resume,
+ .sys_pwr_dm_suspend = sys_pwr_domain_suspend,
+ .sys_pwr_dm_resume = sys_pwr_domain_resume,
+ .sys_gbl_soft_reset = soc_global_soft_reset,
+};
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ rockchip_pd_lock_init();
+ plat_setup_rockchip_pm_ops(&pm_ops);
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+
+ psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
+
+ /* cpu boot from pmusram */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ nonboot_cpus_off();
+ INFO("%s(%d): pd status %x\n", __func__, __LINE__,
+ mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.h b/plat/rockchip/rk3399/drivers/pmu/pmu.h
new file mode 100644
index 0000000..053b6ee
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.h
@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#ifndef __PMU_H__
+#define __PMU_H__
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE 0x80
+#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * Common define for per soc pmu.h
+ *****************************************************************************/
+/* The ways of cores power domain contorlling */
+enum cores_pm_ctr_mode {
+ core_pwr_pd = 0,
+ core_pwr_wfi = 1,
+ core_pwr_wfi_int = 2
+};
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WKUP_CFG(n) ((n) * 4)
+
+#define PMU_CORE_PM_CON(cpu) (0xc0 + (cpu * 4))
+
+/* the shift of bits for cores status */
+enum pmu_core_pwrst_shift {
+ clstl_cpu_wfe = 2,
+ clstl_cpu_wfi = 6,
+ clstb_cpu_wfe = 12,
+ clstb_cpu_wfi = 16
+};
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+enum pmu_powerdomain_id {
+ PD_CPUL0 = 0,
+ PD_CPUL1,
+ PD_CPUL2,
+ PD_CPUL3,
+ PD_CPUB0,
+ PD_CPUB1,
+ PD_SCUL,
+ PD_SCUB,
+ PD_TCPD0,
+ PD_TCPD1,
+ PD_CCI,
+ PD_PERILP,
+ PD_PERIHP,
+ PD_CENTER,
+ PD_VIO,
+ PD_GPU,
+ PD_VCODEC,
+ PD_VDU,
+ PD_RGA,
+ PD_IEP,
+ PD_VO,
+ PD_ISP0 = 22,
+ PD_ISP1,
+ PD_HDCP,
+ PD_GMAC,
+ PD_EMMC,
+ PD_USB3,
+ PD_EDP,
+ PD_GIC,
+ PD_SD,
+ PD_SDIOAUDIO,
+ PD_END
+};
+
+enum powerdomain_state {
+ PMU_POWER_ON = 0,
+ PMU_POWER_OFF,
+};
+
+enum pmu_bus_id {
+ BUS_ID_GPU = 0,
+ BUS_ID_PERILP,
+ BUS_ID_PERIHP,
+ BUS_ID_VCODEC,
+ BUS_ID_VDU,
+ BUS_ID_RGA,
+ BUS_ID_IEP,
+ BUS_ID_VOPB,
+ BUS_ID_VOPL,
+ BUS_ID_ISP0,
+ BUS_ID_ISP1,
+ BUS_ID_HDCP,
+ BUS_ID_USB3,
+ BUS_ID_PERILPM0,
+ BUS_ID_CENTER,
+ BUS_ID_CCIM0,
+ BUS_ID_CCIM1,
+ BUS_ID_VIO,
+ BUS_ID_MSCH0,
+ BUS_ID_MSCH1,
+ BUS_ID_ALIVE,
+ BUS_ID_PMU,
+ BUS_ID_EDP,
+ BUS_ID_GMAC,
+ BUS_ID_EMMC,
+ BUS_ID_CENTER1,
+ BUS_ID_PMUM0,
+ BUS_ID_GIC,
+ BUS_ID_SD,
+ BUS_ID_SDIOAUDIO,
+};
+
+enum pmu_bus_state {
+ BUS_ACTIVE,
+ BUS_IDLE,
+};
+
+/* pmu_cpuapm bit */
+enum pmu_cores_pm_by_wfi {
+ core_pm_en = 0,
+ core_pm_int_wakeup_en,
+ core_pm_resv,
+ core_pm_sft_wakeup_en
+};
+
+enum pmu_wkup_cfg0 {
+ PMU_GPIO0A_POSE_WKUP_EN = 0,
+ PMU_GPIO0B_POSE_WKUP_EN = 8,
+ PMU_GPIO0C_POSE_WKUP_EN = 16,
+ PMU_GPIO0D_POSE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg1 {
+ PMU_GPIO0A_NEGEDGE_WKUP_EN = 0,
+ PMU_GPIO0B_NEGEDGE_WKUP_EN = 7,
+ PMU_GPIO0C_NEGEDGE_WKUP_EN = 16,
+ PMU_GPIO0D_NEGEDGE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg2 {
+ PMU_GPIO1A_POSE_WKUP_EN = 0,
+ PMU_GPIO1B_POSE_WKUP_EN = 7,
+ PMU_GPIO1C_POSE_WKUP_EN = 16,
+ PMU_GPIO1D_POSE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg3 {
+ PMU_GPIO1A_NEGEDGE_WKUP_EN = 0,
+ PMU_GPIO1B_NEGEDGE_WKUP_EN = 7,
+ PMU_GPIO1C_NEGEDGE_WKUP_EN = 16,
+ PMU_GPIO1D_NEGEDGE_WKUP_EN = 24,
+};
+
+/* pmu_wkup_cfg4 */
+enum pmu_wkup_cfg4 {
+ PMU_CLUSTER_L_WKUP_EN = 0,
+ PMU_CLUSTER_B_WKUP_EN,
+ PMU_GPIO_WKUP_EN,
+ PMU_SDIO_WKUP_EN,
+
+ PMU_SDMMC_WKUP_EN,
+ PMU_TIMER_WKUP_EN = 6,
+ PMU_USBDEV_WKUP_EN,
+
+ PMU_SFT_WKUP_EN,
+ PMU_M0_WDT_WKUP_EN,
+ PMU_TIMEOUT_WKUP_EN,
+ PMU_PWM_WKUP_EN,
+
+ PMU_PCIE_WKUP_EN = 13,
+};
+
+enum pmu_pwrdn_con {
+ PMU_A53_L0_PWRDWN_EN = 0,
+ PMU_A53_L1_PWRDWN_EN,
+ PMU_A53_L2_PWRDWN_EN,
+ PMU_A53_L3_PWRDWN_EN,
+
+ PMU_A72_B0_PWRDWN_EN,
+ PMU_A72_B1_PWRDWN_EN,
+ PMU_SCU_L_PWRDWN_EN,
+ PMU_SCU_B_PWRDWN_EN,
+
+ PMU_TCPD0_PWRDWN_EN,
+ PMU_TCPD1_PWRDWN_EN,
+ PMU_CCI_PWRDWN_EN,
+ PMU_PERILP_PWRDWN_EN,
+
+ PMU_PERIHP_PWRDWN_EN,
+ PMU_CENTER_PWRDWN_EN,
+ PMU_VIO_PWRDWN_EN,
+ PMU_GPU_PWRDWN_EN,
+
+ PMU_VCODEC_PWRDWN_EN,
+ PMU_VDU_PWRDWN_EN,
+ PMU_RGA_PWRDWN_EN,
+ PMU_IEP_PWRDWN_EN,
+
+ PMU_VO_PWRDWN_EN,
+ PMU_ISP0_PWRDWN_EN = 22,
+ PMU_ISP1_PWRDWN_EN,
+
+ PMU_HDCP_PWRDWN_EN,
+ PMU_GMAC_PWRDWN_EN,
+ PMU_EMMC_PWRDWN_EN,
+ PMU_USB3_PWRDWN_EN,
+
+ PMU_EDP_PWRDWN_EN,
+ PMU_GIC_PWRDWN_EN,
+ PMU_SD_PWRDWN_EN,
+ PMU_SDIOAUDIO_PWRDWN_EN,
+};
+
+enum pmu_pwrdn_st {
+ PMU_A53_L0_PWRDWN_ST = 0,
+ PMU_A53_L1_PWRDWN_ST,
+ PMU_A53_L2_PWRDWN_ST,
+ PMU_A53_L3_PWRDWN_ST,
+
+ PMU_A72_B0_PWRDWN_ST,
+ PMU_A72_B1_PWRDWN_ST,
+ PMU_SCU_L_PWRDWN_ST,
+ PMU_SCU_B_PWRDWN_ST,
+
+ PMU_TCPD0_PWRDWN_ST,
+ PMU_TCPD1_PWRDWN_ST,
+ PMU_CCI_PWRDWN_ST,
+ PMU_PERILP_PWRDWN_ST,
+
+ PMU_PERIHP_PWRDWN_ST,
+ PMU_CENTER_PWRDWN_ST,
+ PMU_VIO_PWRDWN_ST,
+ PMU_GPU_PWRDWN_ST,
+
+ PMU_VCODEC_PWRDWN_ST,
+ PMU_VDU_PWRDWN_ST,
+ PMU_RGA_PWRDWN_ST,
+ PMU_IEP_PWRDWN_ST,
+
+ PMU_VO_PWRDWN_ST,
+ PMU_ISP0_PWRDWN_ST = 22,
+ PMU_ISP1_PWRDWN_ST,
+
+ PMU_HDCP_PWRDWN_ST,
+ PMU_GMAC_PWRDWN_ST,
+ PMU_EMMC_PWRDWN_ST,
+ PMU_USB3_PWRDWN_ST,
+
+ PMU_EDP_PWRDWN_ST,
+ PMU_GIC_PWRDWN_ST,
+ PMU_SD_PWRDWN_ST,
+ PMU_SDIOAUDIO_PWRDWN_ST,
+
+};
+
+enum pmu_pll_con {
+ PMU_PLL_PD_CFG = 0,
+ PMU_SFT_PLL_PD = 8,
+};
+
+enum pmu_pwermode_con {
+ PMU_PWR_MODE_EN = 0,
+ PMU_WKUP_RST_EN,
+ PMU_INPUT_CLAMP_EN,
+ PMU_OSC_DIS,
+
+ PMU_ALIVE_USE_LF,
+ PMU_PMU_USE_LF,
+ PMU_POWER_OFF_REQ_CFG,
+ PMU_CHIP_PD_EN,
+
+ PMU_PLL_PD_EN,
+ PMU_CPU0_PD_EN,
+ PMU_L2_FLUSH_EN,
+ PMU_L2_IDLE_EN,
+
+ PMU_SCU_PD_EN,
+ PMU_CCI_PD_EN,
+ PMU_PERILP_PD_EN,
+ PMU_CENTER_PD_EN,
+
+ PMU_SREF0_ENTER_EN,
+ PMU_DDRC0_GATING_EN,
+ PMU_DDRIO0_RET_EN,
+ PMU_DDRIO0_RET_DE_REQ,
+
+ PMU_SREF1_ENTER_EN,
+ PMU_DDRC1_GATING_EN,
+ PMU_DDRIO1_RET_EN,
+ PMU_DDRIO1_RET_DE_REQ,
+
+ PMU_CLK_CENTER_SRC_GATE_EN = 26,
+ PMU_CLK_PERILP_SRC_GATE_EN,
+
+ PMU_CLK_CORE_SRC_GATE_EN,
+ PMU_DDRIO_RET_HW_DE_REQ,
+ PMU_SLP_OUTPUT_CFG,
+ PMU_MAIN_CLUSTER,
+};
+
+enum pmu_sft_con {
+ PMU_WKUP_SFT = 0,
+ PMU_INPUT_CLAMP_CFG,
+ PMU_OSC_DIS_CFG,
+ PMU_PMU_LF_EN_CFG,
+
+ PMU_ALIVE_LF_EN_CFG,
+ PMU_24M_EN_CFG,
+ PMU_DBG_PWRUP_L0_CFG,
+ PMU_WKUP_SFT_M0,
+
+ PMU_DDRCTL0_C_SYSREQ_CFG,
+ PMU_DDR0_IO_RET_CFG,
+
+ PMU_DDRCTL1_C_SYSREQ_CFG = 12,
+ PMU_DDR1_IO_RET_CFG,
+};
+
+enum pmu_int_con {
+ PMU_PMU_INT_EN = 0,
+ PMU_PWRMD_WKUP_INT_EN,
+ PMU_WKUP_GPIO0_NEG_INT_EN,
+ PMU_WKUP_GPIO0_POS_INT_EN,
+ PMU_WKUP_GPIO1_NEG_INT_EN,
+ PMU_WKUP_GPIO1_POS_INT_EN,
+};
+
+enum pmu_int_st {
+ PMU_PWRMD_WKUP_INT_ST = 1,
+ PMU_WKUP_GPIO0_NEG_INT_ST,
+ PMU_WKUP_GPIO0_POS_INT_ST,
+ PMU_WKUP_GPIO1_NEG_INT_ST,
+ PMU_WKUP_GPIO1_POS_INT_ST,
+};
+
+enum pmu_gpio0_pos_int_con {
+ PMU_GPIO0A_POS_INT_EN = 0,
+ PMU_GPIO0B_POS_INT_EN = 8,
+ PMU_GPIO0C_POS_INT_EN = 16,
+ PMU_GPIO0D_POS_INT_EN = 24,
+};
+
+enum pmu_gpio0_neg_int_con {
+ PMU_GPIO0A_NEG_INT_EN = 0,
+ PMU_GPIO0B_NEG_INT_EN = 8,
+ PMU_GPIO0C_NEG_INT_EN = 16,
+ PMU_GPIO0D_NEG_INT_EN = 24,
+};
+
+enum pmu_gpio1_pos_int_con {
+ PMU_GPIO1A_POS_INT_EN = 0,
+ PMU_GPIO1B_POS_INT_EN = 8,
+ PMU_GPIO1C_POS_INT_EN = 16,
+ PMU_GPIO1D_POS_INT_EN = 24,
+};
+
+enum pmu_gpio1_neg_int_con {
+ PMU_GPIO1A_NEG_INT_EN = 0,
+ PMU_GPIO1B_NEG_INT_EN = 8,
+ PMU_GPIO1C_NEG_INT_EN = 16,
+ PMU_GPIO1D_NEG_INT_EN = 24,
+};
+
+enum pmu_gpio0_pos_int_st {
+ PMU_GPIO0A_POS_INT_ST = 0,
+ PMU_GPIO0B_POS_INT_ST = 8,
+ PMU_GPIO0C_POS_INT_ST = 16,
+ PMU_GPIO0D_POS_INT_ST = 24,
+};
+
+enum pmu_gpio0_neg_int_st {
+ PMU_GPIO0A_NEG_INT_ST = 0,
+ PMU_GPIO0B_NEG_INT_ST = 8,
+ PMU_GPIO0C_NEG_INT_ST = 16,
+ PMU_GPIO0D_NEG_INT_ST = 24,
+};
+
+enum pmu_gpio1_pos_int_st {
+ PMU_GPIO1A_POS_INT_ST = 0,
+ PMU_GPIO1B_POS_INT_ST = 8,
+ PMU_GPIO1C_POS_INT_ST = 16,
+ PMU_GPIO1D_POS_INT_ST = 24,
+};
+
+enum pmu_gpio1_neg_int_st {
+ PMU_GPIO1A_NEG_INT_ST = 0,
+ PMU_GPIO1B_NEG_INT_ST = 8,
+ PMU_GPIO1C_NEG_INT_ST = 16,
+ PMU_GPIO1D_NEG_INT_ST = 24,
+};
+
+/* pmu power down configure register 0x0050 */
+enum pmu_pwrdn_inten {
+ PMU_A53_L0_PWR_SWITCH_INT_EN = 0,
+ PMU_A53_L1_PWR_SWITCH_INT_EN,
+ PMU_A53_L2_PWR_SWITCH_INT_EN,
+ PMU_A53_L3_PWR_SWITCH_INT_EN,
+
+ PMU_A72_B0_PWR_SWITCH_INT_EN,
+ PMU_A72_B1_PWR_SWITCH_INT_EN,
+ PMU_SCU_L_PWR_SWITCH_INT_EN,
+ PMU_SCU_B_PWR_SWITCH_INT_EN,
+
+ PMU_TCPD0_PWR_SWITCH_INT_EN,
+ PMU_TCPD1_PWR_SWITCH_INT_EN,
+ PMU_CCI_PWR_SWITCH_INT_EN,
+ PMU_PERILP_PWR_SWITCH_INT_EN,
+
+ PMU_PERIHP_PWR_SWITCH_INT_EN,
+ PMU_CENTER_PWR_SWITCH_INT_EN,
+ PMU_VIO_PWR_SWITCH_INT_EN,
+ PMU_GPU_PWR_SWITCH_INT_EN,
+
+ PMU_VCODEC_PWR_SWITCH_INT_EN,
+ PMU_VDU_PWR_SWITCH_INT_EN,
+ PMU_RGA_PWR_SWITCH_INT_EN,
+ PMU_IEP_PWR_SWITCH_INT_EN,
+
+ PMU_VO_PWR_SWITCH_INT_EN,
+ PMU_ISP0_PWR_SWITCH_INT_EN = 22,
+ PMU_ISP1_PWR_SWITCH_INT_EN,
+
+ PMU_HDCP_PWR_SWITCH_INT_EN,
+ PMU_GMAC_PWR_SWITCH_INT_EN,
+ PMU_EMMC_PWR_SWITCH_INT_EN,
+ PMU_USB3_PWR_SWITCH_INT_EN,
+
+ PMU_EDP_PWR_SWITCH_INT_EN,
+ PMU_GIC_PWR_SWITCH_INT_EN,
+ PMU_SD_PWR_SWITCH_INT_EN,
+ PMU_SDIOAUDIO_PWR_SWITCH_INT_EN,
+};
+
+enum pmu_wkup_status {
+ PMU_WKUP_BY_CLSTER_L_INT = 0,
+ PMU_WKUP_BY_CLSTER_b_INT,
+ PMU_WKUP_BY_GPIO_INT,
+ PMU_WKUP_BY_SDIO_DET,
+
+ PMU_WKUP_BY_SDMMC_DET,
+ PMU_WKUP_BY_TIMER = 6,
+ PMU_WKUP_BY_USBDEV_DET,
+
+ PMU_WKUP_BY_M0_SFT,
+ PMU_WKUP_BY_M0_WDT_INT,
+ PMU_WKUP_BY_TIMEOUT,
+ PMU_WKUP_BY_PWM,
+
+ PMU_WKUP_BY_PCIE = 13,
+};
+
+enum pmu_bus_clr {
+ PMU_CLR_GPU = 0,
+ PMU_CLR_PERILP,
+ PMU_CLR_PERIHP,
+ PMU_CLR_VCODEC,
+
+ PMU_CLR_VDU,
+ PMU_CLR_RGA,
+ PMU_CLR_IEP,
+ PMU_CLR_VOPB,
+
+ PMU_CLR_VOPL,
+ PMU_CLR_ISP0,
+ PMU_CLR_ISP1,
+ PMU_CLR_HDCP,
+
+ PMU_CLR_USB3,
+ PMU_CLR_PERILPM0,
+ PMU_CLR_CENTER,
+ PMU_CLR_CCIM1,
+
+ PMU_CLR_CCIM0,
+ PMU_CLR_VIO,
+ PMU_CLR_MSCH0,
+ PMU_CLR_MSCH1,
+
+ PMU_CLR_ALIVE,
+ PMU_CLR_PMU,
+ PMU_CLR_EDP,
+ PMU_CLR_GMAC,
+
+ PMU_CLR_EMMC,
+ PMU_CLR_CENTER1,
+ PMU_CLR_PMUM0,
+ PMU_CLR_GIC,
+
+ PMU_CLR_SD,
+ PMU_CLR_SDIOAUDIO,
+};
+
+/* PMU bus idle request register */
+enum pmu_bus_idle_req {
+ PMU_IDLE_REQ_GPU = 0,
+ PMU_IDLE_REQ_PERILP,
+ PMU_IDLE_REQ_PERIHP,
+ PMU_IDLE_REQ_VCODEC,
+
+ PMU_IDLE_REQ_VDU,
+ PMU_IDLE_REQ_RGA,
+ PMU_IDLE_REQ_IEP,
+ PMU_IDLE_REQ_VOPB,
+
+ PMU_IDLE_REQ_VOPL,
+ PMU_IDLE_REQ_ISP0,
+ PMU_IDLE_REQ_ISP1,
+ PMU_IDLE_REQ_HDCP,
+
+ PMU_IDLE_REQ_USB3,
+ PMU_IDLE_REQ_PERILPM0,
+ PMU_IDLE_REQ_CENTER,
+ PMU_IDLE_REQ_CCIM0,
+
+ PMU_IDLE_REQ_CCIM1,
+ PMU_IDLE_REQ_VIO,
+ PMU_IDLE_REQ_MSCH0,
+ PMU_IDLE_REQ_MSCH1,
+
+ PMU_IDLE_REQ_ALIVE,
+ PMU_IDLE_REQ_PMU,
+ PMU_IDLE_REQ_EDP,
+ PMU_IDLE_REQ_GMAC,
+
+ PMU_IDLE_REQ_EMMC,
+ PMU_IDLE_REQ_CENTER1,
+ PMU_IDLE_REQ_PMUM0,
+ PMU_IDLE_REQ_GIC,
+
+ PMU_IDLE_REQ_SD,
+ PMU_IDLE_REQ_SDIOAUDIO,
+};
+
+/* pmu bus idle status register */
+enum pmu_bus_idle_st {
+ PMU_IDLE_ST_GPU = 0,
+ PMU_IDLE_ST_PERILP,
+ PMU_IDLE_ST_PERIHP,
+ PMU_IDLE_ST_VCODEC,
+
+ PMU_IDLE_ST_VDU,
+ PMU_IDLE_ST_RGA,
+ PMU_IDLE_ST_IEP,
+ PMU_IDLE_ST_VOPB,
+
+ PMU_IDLE_ST_VOPL,
+ PMU_IDLE_ST_ISP0,
+ PMU_IDLE_ST_ISP1,
+ PMU_IDLE_ST_HDCP,
+
+ PMU_IDLE_ST_USB3,
+ PMU_IDLE_ST_PERILPM0,
+ PMU_IDLE_ST_CENTER,
+ PMU_IDLE_ST_CCIM0,
+
+ PMU_IDLE_ST_CCIM1,
+ PMU_IDLE_ST_VIO,
+ PMU_IDLE_ST_MSCH0,
+ PMU_IDLE_ST_MSCH1,
+
+ PMU_IDLE_ST_ALIVE,
+ PMU_IDLE_ST_PMU,
+ PMU_IDLE_ST_EDP,
+ PMU_IDLE_ST_GMAC,
+
+ PMU_IDLE_ST_EMMC,
+ PMU_IDLE_ST_CENTER1,
+ PMU_IDLE_ST_PMUM0,
+ PMU_IDLE_ST_GIC,
+
+ PMU_IDLE_ST_SD,
+ PMU_IDLE_ST_SDIOAUDIO,
+};
+
+enum pmu_bus_idle_ack {
+ PMU_IDLE_ACK_GPU = 0,
+ PMU_IDLE_ACK_PERILP,
+ PMU_IDLE_ACK_PERIHP,
+ PMU_IDLE_ACK_VCODEC,
+
+ PMU_IDLE_ACK_VDU,
+ PMU_IDLE_ACK_RGA,
+ PMU_IDLE_ACK_IEP,
+ PMU_IDLE_ACK_VOPB,
+
+ PMU_IDLE_ACK_VOPL,
+ PMU_IDLE_ACK_ISP0,
+ PMU_IDLE_ACK_ISP1,
+ PMU_IDLE_ACK_HDCP,
+
+ PMU_IDLE_ACK_USB3,
+ PMU_IDLE_ACK_PERILPM0,
+ PMU_IDLE_ACK_CENTER,
+ PMU_IDLE_ACK_CCIM0,
+
+ PMU_IDLE_ACK_CCIM1,
+ PMU_IDLE_ACK_VIO,
+ PMU_IDLE_ACK_MSCH0,
+ PMU_IDLE_ACK_MSCH1,
+
+ PMU_IDLE_ACK_ALIVE,
+ PMU_IDLE_ACK_PMU,
+ PMU_IDLE_ACK_EDP,
+ PMU_IDLE_ACK_GMAC,
+
+ PMU_IDLE_ACK_EMMC,
+ PMU_IDLE_ACK_CENTER1,
+ PMU_IDLE_ACK_PMUM0,
+ PMU_IDLE_ACK_GIC,
+
+ PMU_IDLE_ACK_SD,
+ PMU_IDLE_ACK_SDIOAUDIO,
+};
+
+enum pmu_pwrdn_con1 {
+ PMU_VD_SCU_L_PWRDN_EN = 0,
+ PMU_VD_SCU_B_PWRDN_EN,
+ PMU_VD_CENTER_PWRDN_EN,
+};
+
+#define PMU_WKUP_CFG0 0x00
+#define PMU_WKUP_CFG1 0x04
+#define PMU_WKUP_CFG2 0x08
+#define PMU_WKUP_CFG3 0x0c
+#define PMU_WKUP_CFG4 0x10
+#define PMU_PWRDN_CON 0x14
+#define PMU_PWRDN_ST 0x18
+#define PMU_PLL_CON 0x1c
+#define PMU_PWRMODE_CON 0x20
+#define PMU_SFT_CON 0x24
+#define PMU_INT_CON 0x28
+#define PMU_INT_ST 0x2c
+#define PMU_GPIO0_POS_INT_CON 0x30
+#define PMU_GPIO0_NEG_INT_CON 0x34
+#define PMU_GPIO1_POS_INT_CON 0x38
+#define PMU_GPIO1_NEG_INT_CON 0x3c
+#define PMU_GPIO0_POS_INT_ST 0x40
+#define PMU_GPIO0_NEG_INT_ST 0x44
+#define PMU_GPIO1_POS_INT_ST 0x48
+#define PMU_GPIO1_NEG_INT_ST 0x4c
+#define PMU_PWRDN_INTEN 0x50
+#define PMU_PWRDN_STATUS 0x54
+#define PMU_WAKEUP_STATUS 0x58
+#define PMU_BUS_CLR 0x5c
+#define PMU_BUS_IDLE_REQ 0x60
+#define PMU_BUS_IDLE_ST 0x64
+#define PMU_BUS_IDLE_ACK 0x68
+#define PMU_CCI500_CON 0x6c
+#define PMU_ADB400_CON 0x70
+#define PMU_ADB400_ST 0x74
+#define PMU_POWER_ST 0x78
+#define PMU_CORE_PWR_ST 0x7c
+#define PMU_OSC_CNT 0x80
+#define PMU_PLLLOCK_CNT 0x84
+#define PMU_PLLRST_CNT 0x88
+#define PMU_STABLE_CNT 0x8c
+#define PMU_DDRIO_PWRON_CNT 0x90
+#define PMU_WAKEUP_RST_CLR_CNT 0x94
+#define PMU_DDR_SREF_ST 0x98
+#define PMU_SCU_L_PWRDN_CNT 0x9c
+#define PMU_SCU_L_PWRUP_CNT 0xa0
+#define PMU_SCU_B_PWRDN_CNT 0xa4
+#define PMU_SCU_B_PWRUP_CNT 0xa8
+#define PMU_GPU_PWRDN_CNT 0xac
+#define PMU_GPU_PWRUP_CNT 0xb0
+#define PMU_CENTER_PWRDN_CNT 0xb4
+#define PMU_CENTER_PWRUP_CNT 0xb8
+#define PMU_TIMEOUT_CNT 0xbc
+#define PMU_CPU0APM_CON 0xc0
+#define PMU_CPU1APM_CON 0xc4
+#define PMU_CPU2APM_CON 0xc8
+#define PMU_CPU3APM_CON 0xcc
+#define PMU_CPU0BPM_CON 0xd0
+#define PMU_CPU1BPM_CON 0xd4
+#define PMU_NOC_AUTO_ENA 0xd8
+#define PMU_PWRDN_CON1 0xdc
+
+#define CORES_PM_DISABLE 0x0
+
+#define PD_CTR_LOOP 500
+#define CHK_CPU_LOOP 500
+
+#endif /* __PMU_H__ */
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c
new file mode 100644
index 0000000..f8d66c2
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/soc/soc.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2016, 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 <arch_helpers.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3399_def.h>
+#include <soc.h>
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(GIC500_BASE, GIC500_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CCI500_BASE, CCI500_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRUS_BASE, CRUS_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(RK3399_UART2_BASE, RK3399_UART2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT1, 0xffffffff);
+
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
+ TIMER_EN | TIMER_FMODE);
+}
+
+void sgrf_init(void)
+{
+ /* security config for master */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(5),
+ SGRF_SOC_CON_WMSK | SGRF_SOC_ALLMST_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(6),
+ SGRF_SOC_CON_WMSK | SGRF_SOC_ALLMST_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(7),
+ SGRF_SOC_CON_WMSK | SGRF_SOC_ALLMST_NS);
+
+ /* security config for slave */
+ mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(0),
+ SGRF_PMU_SLV_S_CFGED |
+ SGRF_PMU_SLV_CRYPTO1_NS);
+ mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(1),
+ SGRF_PMU_SLV_CON1_CFG);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(0),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(1),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(2),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(3),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(4),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+
+ /* security config for ddr memery */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16),
+ SGRF_DDR_RGN_BYPS);
+}
+
+static void dma_secure_cfg(uint32_t secure)
+{
+ if (secure) {
+ /* rgn0 secure for dmac0 and dmac1 */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON20_34(22),
+ SGRF_L_MST_S_DDR_RGN(0) | /* dmac0 */
+ SGRF_H_MST_S_DDR_RGN(0) /* dmac1 */
+ );
+
+ /* set dmac0 boot, under secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(8),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(9),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(10),
+ SGRF_DMAC_CFG_S);
+
+ /* dmac0 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST_RLS);
+
+ /* set dmac1 boot, under secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(11),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(12),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(13),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(14),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(15),
+ SGRF_DMAC_CFG_S);
+
+ /* dmac1 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST_RLS);
+ } else {
+ /* rgn non-secure for dmac0 and dmac1 */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON20_34(22),
+ DMAC1_RGN_NS | DMAC0_RGN_NS);
+
+ /* set dmac0 boot, under non-secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(8),
+ DMAC0_BOOT_CFG_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(9),
+ DMAC0_BOOT_PERIPH_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(10),
+ DMAC0_BOOT_ADDR_NS);
+
+ /* dmac0 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST_RLS);
+
+ /* set dmac1 boot, under non-secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(11),
+ DMAC1_BOOT_CFG_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(12),
+ DMAC1_BOOT_PERIPH_L_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(13),
+ DMAC1_BOOT_ADDR_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(14),
+ DMAC1_BOOT_PERIPH_H_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(15),
+ DMAC1_BOOT_IRQ_NS);
+
+ /* dmac1 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST_RLS);
+ }
+}
+
+/* pll suspend */
+struct deepsleep_data_s slp_data;
+
+static void pll_suspend_prepare(uint32_t pll_id)
+{
+ int i;
+
+ if (pll_id == PPLL_ID)
+ for (i = 0; i < PLL_CON_COUNT; i++)
+ slp_data.plls_con[pll_id][i] =
+ mmio_read_32(PMUCRU_BASE + PMUCRU_PPLL_CON(i));
+ else
+ for (i = 0; i < PLL_CON_COUNT; i++)
+ slp_data.plls_con[pll_id][i] =
+ mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i));
+}
+
+static void set_pll_slow_mode(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_SLOW_MODE);
+ else
+ mmio_write_32((CRU_BASE +
+ CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
+}
+
+static void set_pll_normal_mode(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_NOMAL_MODE);
+ else
+ mmio_write_32(CRU_BASE +
+ CRU_PLL_CON(pll_id, 3), PLL_NOMAL_MODE);
+}
+
+static void set_pll_bypass(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE +
+ PMUCRU_PPLL_CON(3), PLL_BYPASS_MODE);
+ else
+ mmio_write_32(CRU_BASE +
+ CRU_PLL_CON(pll_id, 3), PLL_BYPASS_MODE);
+}
+
+static void _pll_suspend(uint32_t pll_id)
+{
+ set_pll_slow_mode(pll_id);
+ set_pll_bypass(pll_id);
+}
+
+void plls_suspend(void)
+{
+ uint32_t i, pll_id;
+
+ for (pll_id = ALPLL_ID; pll_id < END_PLL_ID; pll_id++)
+ pll_suspend_prepare(pll_id);
+
+ for (i = 0; i < CRU_CLKSEL_COUNT; i++)
+ slp_data.cru_clksel_con[i] =
+ mmio_read_32(CRU_BASE +
+ CRU_CLKSEL_OFFSET + i * REG_SIZE);
+
+ for (i = 0; i < PMUCRU_CLKSEL_CONUT; i++)
+ slp_data.pmucru_clksel_con[i] =
+ mmio_read_32(PMUCRU_BASE +
+ PMUCRU_CLKSEL_OFFSET + i * REG_SIZE);
+
+ _pll_suspend(CPLL_ID);
+ _pll_suspend(NPLL_ID);
+ _pll_suspend(VPLL_ID);
+ _pll_suspend(PPLL_ID);
+ _pll_suspend(GPLL_ID);
+ _pll_suspend(ABPLL_ID);
+ _pll_suspend(ALPLL_ID);
+}
+
+static void set_plls_nobypass(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3),
+ PLL_NO_BYPASS_MODE);
+ else
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3),
+ PLL_NO_BYPASS_MODE);
+}
+
+static void plls_resume_prepare(void)
+{
+ int i;
+
+ for (i = 0; i < CRU_CLKSEL_COUNT; i++)
+ mmio_write_32((CRU_BASE + CRU_CLKSEL_OFFSET + i * REG_SIZE),
+ REG_SOC_WMSK | slp_data.cru_clksel_con[i]);
+ for (i = 0; i < PMUCRU_CLKSEL_CONUT; i++)
+ mmio_write_32((PMUCRU_BASE +
+ PMUCRU_CLKSEL_OFFSET + i * REG_SIZE),
+ REG_SOC_WMSK | slp_data.pmucru_clksel_con[i]);
+}
+
+void plls_resume(void)
+{
+ int pll_id;
+
+ plls_resume_prepare();
+ for (pll_id = ALPLL_ID; pll_id < END_PLL_ID; pll_id++) {
+ set_plls_nobypass(pll_id);
+ set_pll_normal_mode(pll_id);
+ }
+}
+
+void soc_global_soft_reset_init(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS);
+}
+
+void __dead2 soc_global_soft_reset(void)
+{
+ uint32_t temp_val;
+
+ set_pll_slow_mode(VPLL_ID);
+ set_pll_slow_mode(NPLL_ID);
+ set_pll_slow_mode(GPLL_ID);
+ set_pll_slow_mode(CPLL_ID);
+ set_pll_slow_mode(PPLL_ID);
+ set_pll_slow_mode(ABPLL_ID);
+ set_pll_slow_mode(ALPLL_ID);
+ temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON) |
+ PMU_RST_BY_FIRST_SFT;
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ dma_secure_cfg(0);
+ sgrf_init();
+ soc_global_soft_reset_init();
+}
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h
new file mode 100644
index 0000000..9100d02
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/soc/soc.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#ifndef __SOC_H__
+#define __SOC_H__
+
+#define GLB_SRST_FST_CFG_VAL 0xfdb9
+#define GLB_SRST_SND_CFG_VAL 0xeca8
+
+#define PMUCRU_PPLL_CON_OFFSET 0x000
+#define PMUCRU_PPLL_CON_BASE_ADDR (PMUCRU_BASE + PMUCRU_PPLL_CON_OFFSET)
+#define PMUCRU_PPLL_CON_CONUT 0x06
+
+#define PMUCRU_PPLL_CON(num) (PMUCRU_PPLL_CON_BASE_ADDR + num * 4)
+#define CRU_PLL_CON(pll_id, num) (CRU_BASE + pll_id * 0x20 + num * 4)
+#define PLL_MODE_MSK 0x03
+#define PLL_MODE_SHIFT 0x08
+#define PLL_BYPASS_MSK 0x01
+#define PLL_BYPASS_SHIFT 0x01
+#define PLL_PWRDN_MSK 0x01
+#define PLL_PWRDN_SHIFT 0x0
+#define PLL_BYPASS BIT(1)
+#define PLL_PWRDN BIT(0)
+
+#define NO_PLL_BYPASS (0x00)
+#define NO_PLL_PWRDN (0x00)
+
+#define PLL_SLOW_MODE BITS_WITH_WMASK(PLL_MODE_MSK,\
+ SLOW_MODE, PLL_MODE_SHIFT)
+#define PLL_BYPASS_MODE BITS_WITH_WMASK(PLL_BYPASS_MSK,\
+ PLL_BYPASS, PLL_BYPASS_SHIFT)
+#define PLL_NO_BYPASS_MODE BITS_WITH_WMASK(PLL_BYPASS_MSK,\
+ NO_PLL_BYPASS, PLL_BYPASS_SHIFT)
+#define PLL_NOMAL_MODE BITS_WITH_WMASK(PLL_MODE_MSK,\
+ NORMAL_MODE, PLL_MODE_SHIFT)
+
+#define PLL_CON_COUNT 0x06
+#define CRU_CLKSEL_COUNT 0x108
+#define CRU_CLKSEL_OFFSET 0x300
+
+#define PMUCRU_CLKSEL_CONUT 0x06
+#define PMUCRU_CLKSEL_OFFSET 0x080
+#define REG_SIZE 0x04
+#define REG_SOC_WMSK 0xffff0000
+
+enum plls_id {
+ ALPLL_ID = 0,
+ ABPLL_ID,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ NPLL_ID,
+ VPLL_ID,
+ PPLL_ID,
+ END_PLL_ID,
+};
+
+enum pll_work_mode {
+ SLOW_MODE = 0x00,
+ NORMAL_MODE = 0x01,
+ DEEP_SLOW_MODE = 0x02,
+};
+
+enum glb_sft_reset {
+ PMU_RST_BY_FIRST_SFT,
+ PMU_RST_BY_SECOND_SFT = BIT(2),
+ PMU_RST_NOT_BY_SFT = BIT(3),
+};
+
+struct deepsleep_data_s {
+ uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT];
+ uint32_t pmucru_clksel_con[PMUCRU_CLKSEL_CONUT];
+ uint32_t cru_clksel_con[CRU_CLKSEL_COUNT];
+};
+
+/**************************************************
+ * secure timer
+ **************************************************/
+
+/* chanal0~5 */
+#define STIMER0_CHN_BASE(n) (STIME_BASE + 0x20 * (n))
+/* chanal6~11 */
+#define STIMER1_CHN_BASE(n) (STIME_BASE + 0x8000 + 0x20 * (n))
+
+ /* low 32 bits */
+#define TIMER_END_COUNT0 0x00
+ /* high 32 bits */
+#define TIMER_END_COUNT1 0x04
+
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+
+ /* low 32 bits */
+#define TIMER_INIT_COUNT0 0x10
+ /* high 32 bits */
+#define TIMER_INIT_COUNT1 0x14
+
+#define TIMER_INTSTATUS 0x18
+#define TIMER_CONTROL_REG 0x1c
+
+#define TIMER_EN 0x1
+
+#define TIMER_FMODE (0x0 << 1)
+#define TIMER_RMODE (0x1 << 1)
+
+/**************************************************
+ * cru reg, offset
+ **************************************************/
+#define CRU_SOFTRST_CON(n) (0x400 + (n) * 4)
+
+#define CRU_DMAC0_RST BIT_WITH_WMSK(3)
+ /* reset release*/
+#define CRU_DMAC0_RST_RLS WMSK_BIT(3)
+
+#define CRU_DMAC1_RST BIT_WITH_WMSK(4)
+ /* reset release*/
+#define CRU_DMAC1_RST_RLS WMSK_BIT(4)
+
+#define CRU_GLB_RST_CON 0x0510
+#define CRU_GLB_SRST_FST 0x0500
+#define CRU_GLB_SRST_SND 0x0504
+
+/**************************************************
+ * pmu cru reg, offset
+ **************************************************/
+#define CRU_PMU_RSTHOLD_CON(n) (0x120 + n * 4)
+/* reset hold*/
+#define CRU_PMU_SGRF_RST_HOLD BIT_WITH_WMSK(6)
+/* reset hold release*/
+#define CRU_PMU_SGRF_RST_RLS WMSK_BIT(6)
+/**************************************************
+ * sgrf reg, offset
+ **************************************************/
+#define SGRF_SOC_CON0_1(n) (0xc000 + (n) * 4)
+#define SGRF_SOC_CON3_7(n) (0xe00c + ((n) - 3) * 4)
+#define SGRF_SOC_CON8_15(n) (0x8020 + ((n) - 8) * 4)
+#define SGRF_PMU_SLV_CON0_1(n) (0xc240 + ((n) - 0) * 4)
+#define SGRF_SLV_SECURE_CON0_4(n) (0xe3c0 + ((n) - 0) * 4)
+#define SGRF_DDRRGN_CON0_16(n) ((n) * 4)
+#define SGRF_DDRRGN_CON20_34(n) (0x50 + ((n) - 20) * 4)
+
+/* security config for master */
+#define SGRF_SOC_CON_WMSK 0xffff0000
+/* All of master in ns */
+#define SGRF_SOC_ALLMST_NS 0xffff
+
+/* security config for slave */
+#define SGRF_SLV_S_WMSK 0xffff0000
+#define SGRF_SLV_S_ALL_NS 0x0
+
+/* security config pmu slave ip */
+/* All of slaves is ns */
+#define SGRF_PMU_SLV_S_NS BIT_WITH_WMSK(0)
+/* slaves secure attr is configed */
+#define SGRF_PMU_SLV_S_CFGED WMSK_BIT(0)
+#define SGRF_PMU_SLV_CRYPTO1_NS WMSK_BIT(1)
+
+#define SGRF_PMUSRAM_S BIT(8)
+
+#define SGRF_PMU_SLV_CON1_CFG (SGRF_SLV_S_WMSK | \
+ SGRF_PMUSRAM_S)
+/* ddr region */
+#define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(9) /* All of ddr rgn is ns */
+
+/* The MST access the ddr rgn n with secure attribution */
+#define SGRF_L_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n))
+/* bits[16:8]*/
+#define SGRF_H_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n) + 8)
+
+/* dmac to periph s or ns*/
+#define SGRF_DMAC_CFG_S 0xffff0000
+
+#define DMAC1_RGN_NS 0xff000000
+#define DMAC0_RGN_NS 0x00ff0000
+
+#define DMAC0_BOOT_CFG_NS 0xfffffff8
+#define DMAC0_BOOT_PERIPH_NS 0xffff0fff
+#define DMAC0_BOOT_ADDR_NS 0xffff0000
+
+#define DMAC1_BOOT_CFG_NS 0xffff0008
+#define DMAC1_BOOT_PERIPH_L_NS 0xffff0fff
+#define DMAC1_BOOT_ADDR_NS 0xffff0000
+#define DMAC1_BOOT_PERIPH_H_NS 0xffffffff
+#define DMAC1_BOOT_IRQ_NS 0xffffffff
+
+#define CPU_BOOT_ADDR_WMASK 0xffff0000
+#define CPU_BOOT_ADDR_ALIGN 16
+
+/*
+ * When system reset in running state, we want the cpus to be reboot
+ * from maskrom (system reboot),
+ * the pmusgrf reset-hold bits needs to be released.
+ * When system wake up from system deep suspend, some soc will be reset
+ * when waked up,
+ * we want the bootcpu to be reboot from pmusram,
+ * the pmusgrf reset-hold bits needs to be held.
+ */
+static inline void pmu_sgrf_rst_hld_release(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS);
+}
+
+static inline void pmu_sgrf_rst_hld(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_HOLD);
+}
+
+/* funciton*/
+void __dead2 soc_global_soft_reset(void);
+void plls_resume(void);
+void plls_suspend(void);
+
+#endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3399/include/platform_def.h b/plat/rockchip/rk3399/include/platform_def.h
new file mode 100644
index 0000000..13f3d50
--- /dev/null
+++ b/plat/rockchip/rk3399/include/platform_def.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014-2016, 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.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <rk3399_def.h>
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CLUSTER_COUNT 2
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 2
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF txet, ro, rw, Size: 512KB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x80000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x8000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_XLAT_TABLES 20
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE BASE_GICD_BASE
+#define PLAT_RK_GICR_BASE BASE_GICR_BASE
+#define PLAT_RK_GICC_BASE 0
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_RK_G1S_IRQS RK3399_G1S_IRQS
+#define PLAT_RK_G0_IRQS RK3399_G0_IRQS
+
+#define PLAT_RK_UART_BASE RK3399_UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3399_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3399_BAUDRATE
+
+#define PLAT_RK_CCI_BASE CCI500_BASE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define RK_PLAT_AARCH_CFG RK_PLAT_CFG1
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
new file mode 100644
index 0000000..7851726
--- /dev/null
+++ b/plat/rockchip/rk3399/platform.mk
@@ -0,0 +1,73 @@
+#
+# Copyright (c) 2016, 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.
+#
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/pmusram \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/include/ \
+
+RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v3/gicv3_main.c \
+ drivers/arm/gic/v3/gicv3_helpers.c \
+ plat/common/plat_gicv3.c \
+ ${RK_PLAT}/common/rockchip_gicv3.c
+
+PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
+ plat/common/aarch64/plat_common.c \
+ plat/common/aarch64/plat_psci_common.c
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/console/console.S \
+ drivers/ti/uart/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \
+ ${RK_PLAT_COMMON}/plat_delay_timer.c \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c
+
+ENABLE_PLAT_COMPAT := 0
diff --git a/plat/rockchip/rk3399/rk3399_def.h b/plat/rockchip/rk3399/rk3399_def.h
new file mode 100644
index 0000000..8562148
--- /dev/null
+++ b/plat/rockchip/rk3399/rk3399_def.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014-2016, 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.
+ */
+
+#ifndef __PLAT_DEF_H__
+#define __PLAT_DEF_H__
+
+#define RK3399_PRIMARY_CPU 0x0
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define SIZE_K(n) ((n) * 1024)
+#define SIZE_M(n) ((n) * 1024 * 1024)
+
+#define CCI500_BASE 0xffb00000
+#define CCI500_SIZE SIZE_M(1)
+
+#define GIC500_BASE 0xfee00000
+#define GIC500_SIZE SIZE_M(2)
+
+#define STIME_BASE 0xff860000
+#define STIME_SIZE SIZE_K(64)
+
+#define CRUS_BASE 0xff750000
+#define CRUS_SIZE SIZE_K(128)
+
+#define SGRF_BASE 0xff330000
+#define SGRF_SIZE SIZE_K(64)
+
+#define PMU_BASE 0xff310000
+#define PMU_SIZE SIZE_K(64)
+
+#define PMUSRAM_BASE 0xff3b0000
+#define PMUSRAM_SIZE SIZE_K(64)
+#define PMUSRAM_RSIZE SIZE_K(8)
+
+/*
+ * include i2c pmu/audio, pwm0-3 rkpwm0-3 uart_dbg,mailbox scr
+ * 0xff650000 -0xff6c0000
+ */
+#define PD_BUS0_BASE 0xff650000
+#define PD_BUS0_SIZE 0x70000
+
+#define PMUCRU_BASE 0xff750000
+#define CRU_BASE 0xff760000
+
+#define COLD_BOOT_BASE 0xffff0000
+
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3399_UART2_BASE (0xff1a0000)
+#define RK3399_UART2_SIZE SIZE_K(64)
+
+#define RK3399_BAUDRATE (1500000)
+#define RK3399_UART_CLOCK (24000000)
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+#define SYS_COUNTER_FREQ_IN_MHZ 24
+
+/* Base rockchip_platform compatible GIC memory map */
+#define BASE_GICD_BASE (GIC500_BASE)
+#define BASE_GICR_BASE (GIC500_BASE + SIZE_M(1))
+
+/*****************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 0
+#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 1
+
+/******************************************************************************
+ * cpu up status
+ ******************************************************************************/
+#define PMU_CPU_HOTPLUG 0xdeadbeaf
+#define PMU_CPU_AUTO_PWRDN 0xabcdef12
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_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 RK3399_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER
+#define RK3399_G0_IRQS ARM_IRQ_SEC_SGI_6
+
+#endif /* __PLAT_DEF_H__ */
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
index 82a4bcb..95bde6c 100644
--- a/tools/cert_create/include/ext.h
+++ b/tools/cert_create/include/ext.h
@@ -35,12 +35,18 @@
#include <openssl/x509v3.h>
/* Extension types supported */
-enum {
+enum ext_type_e {
EXT_TYPE_NVCOUNTER,
EXT_TYPE_PKEY,
EXT_TYPE_HASH
};
+/* NV-Counter types */
+enum nvctr_type_e {
+ NVCTR_TYPE_TFW,
+ NVCTR_TYPE_NTFW
+};
+
/*
* This structure contains the relevant information to create the extensions
* to be included in the certificates. This extensions will be used to
@@ -50,20 +56,21 @@
const char *oid; /* OID of the extension */
const char *sn; /* Short name */
const char *ln; /* Long description */
+ const char *opt; /* Command line option to specify data */
const char *help_msg; /* Help message */
+ const char *arg; /* Argument passed from command line */
int asn1_type; /* OpenSSL ASN1 type of the extension data.
* Supported types are:
* - V_ASN1_INTEGER
* - V_ASN1_OCTET_STRING
*/
- int type;
- const char *opt; /* Command line option to specify data */
- /* Extension data (depends on extension type) */
+ int type; /* See ext_type_e */
+
+ /* Extension attributes (depends on extension type) */
union {
- const char *fn; /* File with extension data */
- int nvcounter; /* Non volatile counter */
- int key; /* Public key */
- } data;
+ int nvctr_type; /* See nvctr_type_e */
+ int key; /* Index into array of registered public keys */
+ } attr;
int alias; /* In case OpenSSL provides an standard
* extension of the same type, add the new
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index 3d2b4ba..c87d988 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -196,9 +196,17 @@
for (j = 0; j < cert->num_ext; j++) {
ext = &extensions[cert->ext[j]];
switch (ext->type) {
+ case EXT_TYPE_NVCOUNTER:
+ /* Counter value must be specified */
+ if ((!ext->optional) && (ext->arg == NULL)) {
+ ERROR("Value for '%s' not specified\n",
+ ext->ln);
+ exit(1);
+ }
+ break;
case EXT_TYPE_PKEY:
/* Key filename must be specified */
- key = &keys[ext->data.key];
+ key = &keys[ext->attr.key];
if (!new_keys && key->fn == NULL) {
ERROR("Key '%s' required by '%s' not "
"specified\n", key->desc,
@@ -211,15 +219,15 @@
* Binary image must be specified
* unless it is explicitly made optional.
*/
- if ((!ext->optional) && (ext->data.fn == NULL)) {
+ if ((!ext->optional) && (ext->arg == NULL)) {
ERROR("Image for '%s' not specified\n",
ext->ln);
exit(1);
}
break;
default:
- ERROR("Unknown extension type in '%s'\n",
- ext->ln);
+ ERROR("Unknown extension type '%d' in '%s'\n",
+ ext->type, ext->ln);
exit(1);
break;
}
@@ -259,7 +267,7 @@
key_t *key = NULL;
cert_t *cert = NULL;
FILE *file = NULL;
- int i, j, ext_nid;
+ int i, j, ext_nid, nvctr;
int c, opt_idx = 0;
const struct option *cmd_opt;
const char *cur_opt;
@@ -331,7 +339,7 @@
case CMD_OPT_EXT:
cur_opt = cmd_opt_get_name(opt_idx);
ext = ext_get_by_opt(cur_opt);
- ext->data.fn = strdup(optarg);
+ ext->arg = strdup(optarg);
break;
case CMD_OPT_KEY:
cur_opt = cmd_opt_get_name(opt_idx);
@@ -420,11 +428,12 @@
*/
switch (ext->type) {
case EXT_TYPE_NVCOUNTER:
+ nvctr = atoi(ext->arg);
CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
- EXT_CRIT, ext->data.nvcounter));
+ EXT_CRIT, nvctr));
break;
case EXT_TYPE_HASH:
- if (ext->data.fn == NULL) {
+ if (ext->arg == NULL) {
if (ext->optional) {
/* Include a hash filled with zeros */
memset(md, 0x0, SHA256_DIGEST_LENGTH);
@@ -434,9 +443,9 @@
}
} else {
/* Calculate the hash of the file */
- if (!sha_file(ext->data.fn, md)) {
+ if (!sha_file(ext->arg, md)) {
ERROR("Cannot calculate hash of %s\n",
- ext->data.fn);
+ ext->arg);
exit(1);
}
}
@@ -446,11 +455,11 @@
break;
case EXT_TYPE_PKEY:
CHECK_NULL(cert_ext, ext_new_key(ext_nid,
- EXT_CRIT, keys[ext->data.key].key));
+ EXT_CRIT, keys[ext->attr.key].key));
break;
default:
- ERROR("Unknown extension type in %s\n",
- cert->cn);
+ ERROR("Unknown extension type '%d' in %s\n",
+ ext->type, cert->cn);
exit(1);
}
diff --git a/tools/cert_create/src/tbbr/tbb_cert.c b/tools/cert_create/src/tbbr/tbb_cert.c
index 7a50ab3..8f7feb5 100644
--- a/tools/cert_create/src/tbbr/tbb_cert.c
+++ b/tools/cert_create/src/tbbr/tbb_cert.c
@@ -49,9 +49,10 @@
.key = ROT_KEY,
.issuer = TRUSTED_BOOT_FW_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_BOOT_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[TRUSTED_KEY_CERT] = {
.id = TRUSTED_KEY_CERT,
@@ -62,10 +63,11 @@
.key = ROT_KEY,
.issuer = TRUSTED_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_WORLD_PK_EXT,
NON_TRUSTED_WORLD_PK_EXT
},
- .num_ext = 2
+ .num_ext = 3
},
[SCP_FW_KEY_CERT] = {
.id = SCP_FW_KEY_CERT,
@@ -76,9 +78,10 @@
.key = TRUSTED_WORLD_KEY,
.issuer = SCP_FW_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SCP_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[SCP_FW_CONTENT_CERT] = {
.id = SCP_FW_CONTENT_CERT,
@@ -89,9 +92,10 @@
.key = SCP_FW_CONTENT_CERT_KEY,
.issuer = SCP_FW_CONTENT_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SCP_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[SOC_FW_KEY_CERT] = {
.id = SOC_FW_KEY_CERT,
@@ -102,9 +106,10 @@
.key = TRUSTED_WORLD_KEY,
.issuer = SOC_FW_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SOC_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[SOC_FW_CONTENT_CERT] = {
.id = SOC_FW_CONTENT_CERT,
@@ -115,9 +120,10 @@
.key = SOC_FW_CONTENT_CERT_KEY,
.issuer = SOC_FW_CONTENT_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SOC_AP_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[TRUSTED_OS_FW_KEY_CERT] = {
.id = TRUSTED_OS_FW_KEY_CERT,
@@ -128,9 +134,10 @@
.key = TRUSTED_WORLD_KEY,
.issuer = TRUSTED_OS_FW_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_OS_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[TRUSTED_OS_FW_CONTENT_CERT] = {
.id = TRUSTED_OS_FW_CONTENT_CERT,
@@ -141,9 +148,10 @@
.key = TRUSTED_OS_FW_CONTENT_CERT_KEY,
.issuer = TRUSTED_OS_FW_CONTENT_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_OS_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[NON_TRUSTED_FW_KEY_CERT] = {
.id = NON_TRUSTED_FW_KEY_CERT,
@@ -154,9 +162,10 @@
.key = NON_TRUSTED_WORLD_KEY,
.issuer = NON_TRUSTED_FW_KEY_CERT,
.ext = {
+ NON_TRUSTED_FW_NVCOUNTER_EXT,
NON_TRUSTED_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[NON_TRUSTED_FW_CONTENT_CERT] = {
.id = NON_TRUSTED_FW_CONTENT_CERT,
@@ -167,9 +176,10 @@
.key = NON_TRUSTED_FW_CONTENT_CERT_KEY,
.issuer = NON_TRUSTED_FW_CONTENT_CERT,
.ext = {
+ NON_TRUSTED_FW_NVCOUNTER_EXT,
NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[FWU_CERT] = {
.id = FWU_CERT,
diff --git a/tools/cert_create/src/tbbr/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
index 8bcb070..5304bd5 100644
--- a/tools/cert_create/src/tbbr/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.c
@@ -44,19 +44,23 @@
static ext_t tbb_ext[] = {
[TRUSTED_FW_NVCOUNTER_EXT] = {
.oid = TRUSTED_FW_NVCOUNTER_OID,
+ .opt = "tfw-nvctr",
+ .help_msg = "Trusted Firmware Non-Volatile counter value",
.sn = "TrustedWorldNVCounter",
.ln = "Trusted World Non-Volatile counter",
.asn1_type = V_ASN1_INTEGER,
.type = EXT_TYPE_NVCOUNTER,
- .data.nvcounter = TRUSTED_WORLD_NVCTR_VALUE
+ .attr.nvctr_type = NVCTR_TYPE_TFW
},
[NON_TRUSTED_FW_NVCOUNTER_EXT] = {
.oid = NON_TRUSTED_FW_NVCOUNTER_OID,
+ .opt = "ntfw-nvctr",
+ .help_msg = "Non-Trusted Firmware Non-Volatile counter value",
.sn = "NormalWorldNVCounter",
- .ln = "Normal World Non-Volatile counter",
+ .ln = "Non-Trusted Firmware Non-Volatile counter",
.asn1_type = V_ASN1_INTEGER,
.type = EXT_TYPE_NVCOUNTER,
- .data.nvcounter = NORMAL_WORLD_NVCTR_VALUE
+ .attr.nvctr_type = NVCTR_TYPE_NTFW
},
[TRUSTED_BOOT_FW_HASH_EXT] = {
.oid = TRUSTED_BOOT_FW_HASH_OID,
@@ -73,7 +77,7 @@
.ln = "Trusted World Public Key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = TRUSTED_WORLD_KEY
+ .attr.key = TRUSTED_WORLD_KEY
},
[NON_TRUSTED_WORLD_PK_EXT] = {
.oid = NON_TRUSTED_WORLD_PK_OID,
@@ -81,7 +85,7 @@
.ln = "Non-Trusted World Public Key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = NON_TRUSTED_WORLD_KEY
+ .attr.key = NON_TRUSTED_WORLD_KEY
},
[SCP_FW_CONTENT_CERT_PK_EXT] = {
.oid = SCP_FW_CONTENT_CERT_PK_OID,
@@ -89,7 +93,7 @@
.ln = "SCP Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = SCP_FW_CONTENT_CERT_KEY
+ .attr.key = SCP_FW_CONTENT_CERT_KEY
},
[SCP_FW_HASH_EXT] = {
.oid = SCP_FW_HASH_OID,
@@ -106,7 +110,7 @@
.ln = "SoC Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = SOC_FW_CONTENT_CERT_KEY
+ .attr.key = SOC_FW_CONTENT_CERT_KEY
},
[SOC_AP_FW_HASH_EXT] = {
.oid = SOC_AP_FW_HASH_OID,
@@ -123,7 +127,7 @@
.ln = "Trusted OS Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
+ .attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
},
[TRUSTED_OS_FW_HASH_EXT] = {
.oid = TRUSTED_OS_FW_HASH_OID,
@@ -140,7 +144,7 @@
.ln = "Non-Trusted Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = NON_TRUSTED_FW_CONTENT_CERT_KEY
+ .attr.key = NON_TRUSTED_FW_CONTENT_CERT_KEY
},
[NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = {
.oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID,