aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/st/etzpc/etzpc.c
diff options
context:
space:
mode:
authorAlistair Delva <adelva@google.com>2021-02-15 12:43:29 -0800
committerAlistair Delva <adelva@google.com>2021-02-15 12:44:34 -0800
commitfaa476c0caaa598afa5a6109d17102db5fe35ec6 (patch)
tree37a21c69306801ee7cdda5167a30896c8740155b /drivers/st/etzpc/etzpc.c
parentb00a71fc312c9781fa6f404dccfb55b062b2ccac (diff)
parent66306814586b1bf6bcb859aaad218ec3bb090e94 (diff)
downloadplatform_external_arm-trusted-firmware-faa476c0caaa598afa5a6109d17102db5fe35ec6.tar.gz
platform_external_arm-trusted-firmware-faa476c0caaa598afa5a6109d17102db5fe35ec6.tar.bz2
platform_external_arm-trusted-firmware-faa476c0caaa598afa5a6109d17102db5fe35ec6.zip
Merge branch 'aosp/upstream-master' into HEADandroid-s-preview-1
This keeps the bl31 interface change reverted which still has not been fixed in upstream U-Boot for rockchip devices. Test: CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rk3399 \ DEBUG=0 ERROR_DEPRECATED=1 bl31 Signed-off-by: Alistair Delva <adelva@google.com> Change-Id: I7c3972a7b767715efb05593096d5d92dba14c609
Diffstat (limited to 'drivers/st/etzpc/etzpc.c')
-rw-r--r--drivers/st/etzpc/etzpc.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c
new file mode 100644
index 000000000..ff52a22d9
--- /dev/null
+++ b/drivers/st/etzpc/etzpc.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+/* Device Tree related definitions */
+#define ETZPC_COMPAT "st,stm32-etzpc"
+#define ETZPC_LOCK_MASK 0x1U
+#define ETZPC_MODE_SHIFT 8
+#define ETZPC_MODE_MASK GENMASK(1, 0)
+#define ETZPC_ID_SHIFT 16
+#define ETZPC_ID_MASK GENMASK(7, 0)
+
+/* ID Registers */
+#define ETZPC_TZMA0_SIZE 0x000U
+#define ETZPC_DECPROT0 0x010U
+#define ETZPC_DECPROT_LOCK0 0x030U
+#define ETZPC_HWCFGR 0x3F0U
+#define ETZPC_VERR 0x3F4U
+
+/* ID Registers fields */
+#define ETZPC_TZMA0_SIZE_LOCK BIT(31)
+#define ETZPC_DECPROT0_MASK GENMASK(1, 0)
+#define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0
+#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8
+#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16
+#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24
+
+#define DECPROT_SHIFT 1
+#define IDS_PER_DECPROT_REGS 16U
+#define IDS_PER_DECPROT_LOCK_REGS 32U
+
+/*
+ * etzpc_instance.
+ * base : register base address set during init given by user
+ * chunk_size : supported TZMA size steps
+ * num_tzma: number of TZMA zone read from register at init
+ * num_ahb_sec : number of securable AHB master zone read from register
+ * num_per_sec : number of securable AHB & APB Peripherals read from register
+ * revision : IP revision read from register at init
+ */
+struct etzpc_instance {
+ uintptr_t base;
+ uint8_t chunck_size;
+ uint8_t num_tzma;
+ uint8_t num_per_sec;
+ uint8_t num_ahb_sec;
+ uint8_t revision;
+};
+
+/* Only 1 instance of the ETZPC is expected per platform */
+static struct etzpc_instance etzpc_dev;
+
+/*
+ * Implementation uses uint8_t to store each securable DECPROT configuration.
+ * When resuming from deep suspend, the DECPROT configurations are restored.
+ */
+#define PERIPH_LOCK_BIT BIT(7)
+#define PERIPH_ATTR_MASK GENMASK(2, 0)
+
+#if ENABLE_ASSERTIONS
+static bool valid_decprot_id(unsigned int id)
+{
+ return id < (unsigned int)etzpc_dev.num_per_sec;
+}
+
+static bool valid_tzma_id(unsigned int id)
+{
+ return id < (unsigned int)etzpc_dev.num_tzma;
+}
+#endif
+
+/*
+ * etzpc_configure_decprot : Load a DECPROT configuration
+ * decprot_id : ID of the IP
+ * decprot_attr : Restriction access attribute
+ */
+void etzpc_configure_decprot(uint32_t decprot_id,
+ enum etzpc_decprot_attributes decprot_attr)
+{
+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
+ uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+ uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK;
+
+ assert(valid_decprot_id(decprot_id));
+
+ mmio_clrsetbits_32(etzpc_dev.base + ETZPC_DECPROT0 + offset,
+ (uint32_t)ETZPC_DECPROT0_MASK << shift,
+ masked_decprot << shift);
+}
+
+/*
+ * etzpc_get_decprot : Get the DECPROT attribute
+ * decprot_id : ID of the IP
+ * return : Attribute of this DECPROT
+ */
+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id)
+{
+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
+ uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+ uintptr_t base_decprot = etzpc_dev.base + offset;
+ uint32_t value;
+
+ assert(valid_decprot_id(decprot_id));
+
+ value = (mmio_read_32(base_decprot + ETZPC_DECPROT0) >> shift) &
+ ETZPC_DECPROT0_MASK;
+
+ return (enum etzpc_decprot_attributes)value;
+}
+
+/*
+ * etzpc_lock_decprot : Lock access to the DECPROT attribute
+ * decprot_id : ID of the IP
+ */
+void etzpc_lock_decprot(uint32_t decprot_id)
+{
+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
+ uint32_t shift = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
+ uintptr_t base_decprot = etzpc_dev.base + offset;
+
+ assert(valid_decprot_id(decprot_id));
+
+ mmio_write_32(base_decprot + ETZPC_DECPROT_LOCK0, shift);
+}
+
+/*
+ * etzpc_configure_tzma : Configure the target TZMA read only size
+ * tzma_id : ID of the memory
+ * tzma_value : read-only size
+ */
+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value)
+{
+ assert(valid_tzma_id(tzma_id));
+
+ mmio_write_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id), tzma_value);
+}
+
+/*
+ * etzpc_get_tzma : Get the target TZMA read only size
+ * tzma_id : TZMA ID
+ * return : Size of read only size
+ */
+uint16_t etzpc_get_tzma(uint32_t tzma_id)
+{
+ assert(valid_tzma_id(tzma_id));
+
+ return (uint16_t)mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id));
+}
+
+/*
+ * etzpc_lock_tzma : Lock the target TZMA
+ * tzma_id : TZMA ID
+ */
+void etzpc_lock_tzma(uint32_t tzma_id)
+{
+ assert(valid_tzma_id(tzma_id));
+
+ mmio_setbits_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id), ETZPC_TZMA0_SIZE_LOCK);
+}
+
+/*
+ * etzpc_get_lock_tzma : Return the lock status of the target TZMA
+ * tzma_id : TZMA ID
+ * return : True if TZMA is locked, false otherwise
+ */
+bool etzpc_get_lock_tzma(uint32_t tzma_id)
+{
+ uint32_t tzma_size;
+
+ assert(valid_tzma_id(tzma_id));
+
+ tzma_size = mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id));
+
+ return (tzma_size & ETZPC_TZMA0_SIZE_LOCK) != 0;
+}
+
+/*
+ * etzpc_get_num_per_sec : Return the DECPROT ID limit value
+ */
+uint8_t etzpc_get_num_per_sec(void)
+{
+ return etzpc_dev.num_per_sec;
+}
+
+/*
+ * etzpc_get_revision : Return the ETZPC IP revision
+ */
+uint8_t etzpc_get_revision(void)
+{
+ return etzpc_dev.revision;
+}
+
+/*
+ * etzpc_get_base_address : Return the ETZPC IP base address
+ */
+uintptr_t etzpc_get_base_address(void)
+{
+ return etzpc_dev.base;
+}
+
+/*
+ * etzpc_init : Initialize the ETZPC driver
+ * Return 0 on success and a negative errno on failure
+ */
+int etzpc_init(void)
+{
+ uint32_t hwcfg;
+ int node;
+ struct dt_node_info etzpc_info;
+
+ node = dt_get_node(&etzpc_info, -1, ETZPC_COMPAT);
+ if (node < 0) {
+ return -EIO;
+ }
+
+ /* Check ETZPC is secure only */
+ if (etzpc_info.status != DT_SECURE) {
+ return -EACCES;
+ }
+
+ etzpc_dev.base = etzpc_info.base;
+
+ hwcfg = mmio_read_32(etzpc_dev.base + ETZPC_HWCFGR);
+
+ etzpc_dev.num_tzma = (uint8_t)(hwcfg >> ETZPC_HWCFGR_NUM_TZMA_SHIFT);
+ etzpc_dev.num_per_sec = (uint8_t)(hwcfg >>
+ ETZPC_HWCFGR_NUM_PER_SEC_SHIFT);
+ etzpc_dev.num_ahb_sec = (uint8_t)(hwcfg >>
+ ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT);
+ etzpc_dev.chunck_size = (uint8_t)(hwcfg >>
+ ETZPC_HWCFGR_CHUNCKS1N4_SHIFT);
+
+ etzpc_dev.revision = mmio_read_8(etzpc_dev.base + ETZPC_VERR);
+
+ VERBOSE("ETZPC version 0x%x", etzpc_dev.revision);
+
+ return 0;
+}