Merge "Plat AXG: Fix PLAT_MAX_PWR_LVL value" into integration
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index f500938..91a5621 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -516,8 +516,8 @@
Texas Instruments platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Andrew F. Davis <afd@ti.com>
-:G: `glneo`_
+:M: Nishanth Menon <nm@ti.com>
+:G: `nmenon`_
:F: docs/plat/ti-k3.rst
:F: plat/ti/
@@ -651,5 +651,6 @@
.. _john-powell-arm: https://github.com/john-powell-arm
.. _raghuncstate: https://github.com/raghuncstate
.. _CJKay: https://github.com/cjkay
+.. _nmenon: https://github.com/nmenon
.. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index e901e0c..d859cc5 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -249,6 +249,9 @@
- ``ERRATA_A76_1868343``: This applies errata 1868343 workaround to Cortex-A76
CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
+- ``ERRATA_A76_1946160``: This applies errata 1946160 workaround to Cortex-A76
+ CPU. This needs to be enabled only for revisions r3p0 - r4p1 of the CPU.
+
For Cortex-A77, the following errata build flags are defined :
- ``ERRATA_A77_1508412``: This applies errata 1508412 workaround to Cortex-A77
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index 2e50068..a1d2313 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -94,6 +94,10 @@
- ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
+- ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config
+ device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest
+ file name contains pattern optee_sp.
+
For a better understanding of these options, the Arm development platform memory
map is explained in the :ref:`Firmware Design`.
diff --git a/drivers/marvell/uart/a3700_console.S b/drivers/marvell/uart/a3700_console.S
index d184a2d..dc374ee 100644
--- a/drivers/marvell/uart/a3700_console.S
+++ b/drivers/marvell/uart/a3700_console.S
@@ -232,6 +232,11 @@
* ---------------------------------------------
*/
func console_a3700_core_flush
+ /* Wait for the TX FIFO to be empty */
+1: ldr w1, [x0, #UART_STATUS_REG]
+ and w1, w1, #UARTLSR_TXFIFOEMPTY
+ cmp w1, #UARTLSR_TXFIFOEMPTY
+ b.ne 1b
ret
endfunc console_a3700_core_flush
diff --git a/fdts/tc0.dts b/fdts/tc0.dts
index 763c813..5438474 100644
--- a/fdts/tc0.dts
+++ b/fdts/tc0.dts
@@ -109,6 +109,17 @@
reg = <0x0 0x80000000 0x0 0x7d000000>;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ optee@0xfce00000 {
+ reg = <0x00000000 0xfce00000 0 0x00200000>;
+ no-map;
+ };
+ };
+
psci {
compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
method = "smc";
@@ -370,4 +381,17 @@
};
};
};
+
+ ffa {
+ compatible = "arm,ffa";
+ conduit = "smc";
+ mem_share_buffer = "tx";
+ };
+
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "ffa";
+ };
+ };
};
diff --git a/include/drivers/allwinner/axp.h b/include/drivers/allwinner/axp.h
index 9c0035f..222820b 100644
--- a/include/drivers/allwinner/axp.h
+++ b/include/drivers/allwinner/axp.h
@@ -9,6 +9,10 @@
#include <stdint.h>
+#define AXP20X_MODE_REG 0x3e
+#define AXP20X_MODE_I2C 0x00
+#define AXP20X_MODE_RSB 0x7c
+
#define NA 0xff
enum {
diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h
index c6315be..aa628df 100644
--- a/include/plat/arm/common/fconf_arm_sp_getter.h
+++ b/include/plat/arm/common/fconf_arm_sp_getter.h
@@ -13,7 +13,7 @@
/* arm_sp getter */
#define arm__sp_getter(prop) arm_sp.prop
-#define ARM_SP_MAX_SIZE U(0x80000)
+#define ARM_SP_MAX_SIZE U(0xb0000)
#define ARM_SP_OWNER_NAME_LEN U(8)
struct arm_sp_t {
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 2c99cdc..4f7f4bb 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -430,6 +430,61 @@
b cpu_rev_var_ls
endfunc check_errata_1868343
+/* --------------------------------------------------
+ * Errata Workaround for A76 Erratum 1946160.
+ * This applies to revisions r3p0 - r4p1 of A76.
+ * It also exists in r0p0 - r2p0 but there is no fix
+ * in those revisions.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a76_1946160_wa
+ /* Compare x0 against revisions r3p0 - r4p1 */
+ mov x17, x30
+ bl check_errata_1946160
+ cbz x0, 1f
+
+ mov x0, #3
+ msr S3_6_C15_C8_0, x0
+ ldr x0, =0x10E3900002
+ msr S3_6_C15_C8_2, x0
+ ldr x0, =0x10FFF00083
+ msr S3_6_C15_C8_3, x0
+ ldr x0, =0x2001003FF
+ msr S3_6_C15_C8_1, x0
+
+ mov x0, #4
+ msr S3_6_C15_C8_0, x0
+ ldr x0, =0x10E3800082
+ msr S3_6_C15_C8_2, x0
+ ldr x0, =0x10FFF00083
+ msr S3_6_C15_C8_3, x0
+ ldr x0, =0x2001003FF
+ msr S3_6_C15_C8_1, x0
+
+ mov x0, #5
+ msr S3_6_C15_C8_0, x0
+ ldr x0, =0x10E3800200
+ msr S3_6_C15_C8_2, x0
+ ldr x0, =0x10FFF003E0
+ msr S3_6_C15_C8_3, x0
+ ldr x0, =0x2001003FF
+ msr S3_6_C15_C8_1, x0
+
+ isb
+1:
+ ret x17
+endfunc errata_a76_1946160_wa
+
+func check_errata_1946160
+ /* Applies to revisions r3p0 - r4p1. */
+ mov x1, #0x30
+ mov x2, #0x41
+ b cpu_rev_var_range
+endfunc check_errata_1946160
+
func check_errata_cve_2018_3639
#if WORKAROUND_CVE_2018_3639
mov x0, #ERRATA_APPLIES
@@ -509,6 +564,11 @@
bl errata_a76_1791580_wa
#endif
+#if ERRATA_A76_1946160
+ mov x0, x18
+ bl errata_a76_1946160_wa
+#endif
+
#if WORKAROUND_CVE_2018_3639
/* If the PE implements SSBS, we don't need the dynamic workaround */
mrs x0, id_aa64pfr1_el1
@@ -592,6 +652,7 @@
report_errata ERRATA_A76_1791580, cortex_a76, 1791580
report_errata ERRATA_A76_1165522, cortex_a76, 1165522
report_errata ERRATA_A76_1868343, cortex_a76, 1868343
+ report_errata ERRATA_A76_1946160, cortex_a76, 1946160
report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639
report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953
report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 084e6e7..da0157f 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -278,6 +278,10 @@
# only to revision <= r4p0 of the Cortex A76 cpu.
ERRATA_A76_1868343 ?=0
+# Flag to apply erratum 1946160 workaround during reset. This erratum applies
+# only to revisions r3p0 - r4p1 of the Cortex A76 cpu.
+ERRATA_A76_1946160 ?=0
+
# Flag to apply erratum 1508412 workaround during reset. This erratum applies
# only to revision <= r1p0 of the Cortex A77 cpu.
ERRATA_A77_1508412 ?=0
@@ -555,6 +559,10 @@
$(eval $(call assert_boolean,ERRATA_A76_1868343))
$(eval $(call add_define,ERRATA_A76_1868343))
+# Process ERRATA_A76_1946160 flag
+$(eval $(call assert_boolean,ERRATA_A76_1946160))
+$(eval $(call add_define,ERRATA_A76_1946160))
+
# Process ERRATA_A77_1508412 flag
$(eval $(call assert_boolean,ERRATA_A77_1508412))
$(eval $(call add_define,ERRATA_A77_1508412))
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index e2dcfa8..72bd6bd 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -42,6 +42,11 @@
define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64) | \
define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64))
+/* Internally PSCI uses a uint16_t for various cpu indexes so
+ * define a limit to number of CPUs that can be initialised.
+ */
+#define PSCI_MAX_CPUS_INDEX 0xFFFFU
+
/*
* Helper functions to get/set the fields of PSCI per-cpu data.
*/
@@ -134,7 +139,7 @@
unsigned char level;
/* For indexing the psci_lock array*/
- unsigned char lock_index;
+ uint16_t lock_index;
} non_cpu_pd_node_t;
typedef struct cpu_pwr_domain_node {
@@ -239,7 +244,7 @@
#endif /* HW_ASSISTED_COHERENCY */
static inline void psci_lock_init(non_cpu_pd_node_t *non_cpu_pd_node,
- unsigned char idx)
+ uint16_t idx)
{
non_cpu_pd_node[idx].lock_index = idx;
}
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index d1ec998..9c37d63 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -17,6 +17,12 @@
#include "psci_private.h"
+/*
+ * Check that PLATFORM_CORE_COUNT fits into the number of cores
+ * that can be represented by PSCI_MAX_CPUS_INDEX.
+ */
+CASSERT(PLATFORM_CORE_COUNT <= (PSCI_MAX_CPUS_INDEX + 1U), assert_psci_cores_overflow);
+
/*******************************************************************************
* Per cpu non-secure contexts used to program the architectural state prior
* return to the normal world.
@@ -34,11 +40,13 @@
* Function which initializes the 'psci_non_cpu_pd_nodes' or the
* 'psci_cpu_pd_nodes' corresponding to the power level.
******************************************************************************/
-static void __init psci_init_pwr_domain_node(unsigned char node_idx,
+static void __init psci_init_pwr_domain_node(uint16_t node_idx,
unsigned int parent_idx,
unsigned char level)
{
if (level > PSCI_CPU_PWR_LVL) {
+ assert(node_idx < PSCI_NUM_NON_CPU_PWR_DOMAINS);
+
psci_non_cpu_pd_nodes[node_idx].level = level;
psci_lock_init(psci_non_cpu_pd_nodes, node_idx);
psci_non_cpu_pd_nodes[node_idx].parent_node = parent_idx;
@@ -47,6 +55,8 @@
} else {
psci_cpu_data_t *svc_cpu_data;
+ assert(node_idx < PLATFORM_CORE_COUNT);
+
psci_cpu_pd_nodes[node_idx].parent_node = parent_idx;
/* Initialize with an invalid mpidr */
@@ -144,7 +154,7 @@
for (j = node_index;
j < (node_index + num_children); j++)
- psci_init_pwr_domain_node((unsigned char)j,
+ psci_init_pwr_domain_node((uint16_t)j,
parent_node_index - 1U,
(unsigned char)level);
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
index 997aaa6..901d888 100644
--- a/plat/allwinner/common/allwinner-common.mk
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -48,6 +48,10 @@
ERRATA_A53_835769 := 1
ERRATA_A53_843419 := 1
ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
+
+# The traditional U-Boot load address is 160MB into DRAM.
+PRELOADED_BL33_BASE ?= 0x4a000000
# The reset vector can be changed for each CPU.
PROGRAMMABLE_RESET_ADDRESS := 1
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 975cc48..93720ff 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -25,9 +25,6 @@
#define BL31_NOBITS_BASE (SUNXI_SRAM_A1_BASE + 0x1000)
#define BL31_NOBITS_LIMIT (SUNXI_SRAM_A1_BASE + SUNXI_SRAM_A1_SIZE)
-/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */
-#define PLAT_SUNXI_NS_IMAGE_OFFSET (SUNXI_DRAM_BASE + (160U << 20))
-
/* How much memory to reserve as secure for BL32, if configured */
#define SUNXI_DRAM_SEC_SIZE (32U << 20)
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index e836a34..9c8eaa4 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -57,7 +57,7 @@
for (i = 0; i < 2048 / sizeof(uint64_t); i++) {
uint32_t *dtb_base;
- if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET)
+ if (u_boot_base[i] != PRELOADED_BL33_BASE)
continue;
/* Does the suspected U-Boot size look anyhow reasonable? */
@@ -96,7 +96,7 @@
* Tell BL31 where the non-trusted software image
* is located and the entry state information
*/
- bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS);
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index 0ca18ad..5b536a0 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -27,7 +27,7 @@
MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE,
MT_RW_DATA | MT_SECURE),
- MAP_REGION(PLAT_SUNXI_NS_IMAGE_OFFSET,
+ MAP_REGION(PRELOADED_BL33_BASE,
SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE,
SUNXI_DRAM_MAP_SIZE,
MT_RO_DATA | MT_NS),
@@ -39,15 +39,6 @@
return SUNXI_OSC24M_CLK_IN_HZ;
}
-uintptr_t plat_get_ns_image_entrypoint(void)
-{
-#ifdef PRELOADED_BL33_BASE
- return PRELOADED_BL33_BASE;
-#else
- return PLAT_SUNXI_NS_IMAGE_OFFSET;
-#endif
-}
-
void sunxi_configure_mmu_el3(int flags)
{
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
@@ -125,11 +116,9 @@
device_bit = BIT(6);
break;
case SUNXI_SOC_H6:
- if (use_rsb)
- return -ENODEV;
- pin_func = 0x33;
+ pin_func = use_rsb ? 0x22 : 0x33;
device_bit = BIT(16);
- reset_offset = 0x19c;
+ reset_offset = use_rsb ? 0x1bc : 0x19c;
break;
case SUNXI_SOC_A64:
pin_func = use_rsb ? 0x22 : 0x33;
@@ -157,7 +146,7 @@
if (socid != SUNXI_SOC_H6)
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit);
else
- mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0));
+ mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0));
/* assert, then de-assert reset of I2C/RSB controller */
mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
index 92c83b0..98b91c3 100644
--- a/plat/allwinner/common/sunxi_security.c
+++ b/plat/allwinner/common/sunxi_security.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,16 +7,11 @@
#include <common/debug.h>
#include <lib/mmio.h>
+#include <sunxi_ccu.h>
#include <sunxi_mmap.h>
#include <sunxi_private.h>
+#include <sunxi_spc.h>
-#ifdef SUNXI_SPC_BASE
-#define SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4)
-#define SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x8)
-#define SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0xc)
-#endif
-
-#define R_PRCM_SEC_SWITCH_REG 0x1d0
#define DMA_SEC_REG 0x20
/*
@@ -27,20 +22,18 @@
*/
void sunxi_security_setup(void)
{
-#ifdef SUNXI_SPC_BASE
int i;
INFO("Configuring SPC Controller\n");
/* SPC setup: set all devices to non-secure */
- for (i = 0; i < 6; i++)
- mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff);
-#endif
+ for (i = 0; i < SUNXI_SPC_NUM_PORTS; i++)
+ mmio_write_32(SUNXI_SPC_DECPORT_SET_REG(i), 0xffffffff);
/* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
/* Set R_PRCM bus clocks to non-secure */
- mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x1);
+ mmio_write_32(SUNXI_R_PRCM_SEC_SWITCH_REG, 0x1);
/* Set all DMA channels (16 max.) to non-secure */
mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_ccu.h b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h
new file mode 100644
index 0000000..2a24886
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x02f0)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x01d0)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index 9d2542f..6c847d3 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -36,7 +36,6 @@
#define SUNXI_MSGBOX_BASE 0x01c17000
#define SUNXI_SPINLOCK_BASE 0x01c18000
#define SUNXI_CCU_BASE 0x01c20000
-#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x2f0)
#define SUNXI_PIO_BASE 0x01c20800
#define SUNXI_TIMER_BASE 0x01c20c00
#define SUNXI_WDOG_BASE 0x01c20ca0
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_spc.h b/plat/allwinner/sun50i_a64/include/sunxi_spc.h
new file mode 100644
index 0000000..5ba7e18
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_spc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+#define SUNXI_SPC_NUM_PORTS 6
+
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x0c * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x0c * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x000c + 0x0c * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c
index 5b7d76a..80a69c3 100644
--- a/plat/allwinner/sun50i_a64/sunxi_power.c
+++ b/plat/allwinner/sun50i_a64/sunxi_power.c
@@ -92,21 +92,13 @@
if (ret)
return ret;
- /* Start with 400 KHz to issue the I2C->RSB switch command. */
- ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 400000);
- if (ret)
- return ret;
-
- /*
- * Initiate an I2C transaction to write 0x7c into register 0x3e,
- * switching the PMIC to RSB mode.
- */
- ret = rsb_set_device_mode(0x7c3e00);
+ /* Switch to the recommended 3 MHz bus clock. */
+ ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
if (ret)
return ret;
- /* Now in RSB mode, switch to the recommended 3 MHz. */
- ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
+ /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
+ ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
if (ret)
return ret;
@@ -156,6 +148,11 @@
pmic = AXP803_RSB;
axp_setup_regulators(fdt);
+ /* Switch the PMIC back to I2C mode. */
+ ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
+ if (ret)
+ return ret;
+
break;
default:
return -ENODEV;
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_ccu.h b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h
new file mode 100644
index 0000000..85fbb90
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index 702db77..2d7b098 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -30,8 +30,8 @@
#define SUNXI_DMA_BASE 0x03002000
#define SUNXI_MSGBOX_BASE 0x03003000
#define SUNXI_CCU_BASE 0x03001000
-#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0xf00)
#define SUNXI_PIO_BASE 0x0300b000
+#define SUNXI_SPC_BASE 0x03008000
#define SUNXI_TIMER_BASE 0x03009000
#define SUNXI_WDOG_BASE 0x030090a0
#define SUNXI_THS_BASE 0x05070400
@@ -55,6 +55,7 @@
#define SUNXI_R_TWD_BASE 0x07020800
#define SUNXI_R_CPUCFG_BASE 0x07000400
#define SUNXI_R_I2C_BASE 0x07081400
+#define SUNXI_R_RSB_BASE 0x07083000
#define SUNXI_R_UART_BASE 0x07080000
#define SUNXI_R_PIO_BASE 0x07022000
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_spc.h b/plat/allwinner/sun50i_h6/include/sunxi_spc.h
new file mode 100644
index 0000000..0f5965b
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_spc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+#define SUNXI_SPC_NUM_PORTS 14
+
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk
index 4ecc57c..1c98919 100644
--- a/plat/allwinner/sun50i_h6/platform.mk
+++ b/plat/allwinner/sun50i_h6/platform.mk
@@ -8,4 +8,4 @@
include plat/allwinner/common/allwinner-common.mk
BL31_SOURCES += drivers/allwinner/axp/axp805.c \
- drivers/mentor/i2c/mi2cv.c
+ drivers/allwinner/sunxi_rsb.c
diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c
index 443015b..a7865a5 100644
--- a/plat/allwinner/sun50i_h6/sunxi_power.c
+++ b/plat/allwinner/sun50i_h6/sunxi_power.c
@@ -6,20 +6,17 @@
*/
#include <errno.h>
-#include <string.h>
-#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/allwinner/axp.h>
-#include <drivers/delay_timer.h>
-#include <drivers/mentor/mi2cv.h>
-#include <lib/mmio.h>
+#include <drivers/allwinner/sunxi_rsb.h>
#include <sunxi_def.h>
#include <sunxi_mmap.h>
#include <sunxi_private.h>
-#define AXP805_ADDR 0x36
+#define AXP805_HW_ADDR 0x745
+#define AXP805_RT_ADDR 0x3a
static enum pmic_type {
UNKNOWN,
@@ -28,67 +25,67 @@
int axp_read(uint8_t reg)
{
- uint8_t val;
- int ret;
-
- ret = i2c_write(AXP805_ADDR, 0, 0, ®, 1);
- if (ret == 0)
- ret = i2c_read(AXP805_ADDR, 0, 0, &val, 1);
- if (ret) {
- ERROR("PMIC: Cannot read AXP805 register %02x\n", reg);
- return ret;
- }
-
- return val;
+ return rsb_read(AXP805_RT_ADDR, reg);
}
int axp_write(uint8_t reg, uint8_t val)
{
- int ret;
-
- ret = i2c_write(AXP805_ADDR, reg, 1, &val, 1);
- if (ret)
- ERROR("PMIC: Cannot write AXP805 register %02x\n", reg);
-
- return ret;
+ return rsb_write(AXP805_RT_ADDR, reg, val);
}
-static int axp805_probe(void)
+static int rsb_init(void)
{
int ret;
- /* Switch the AXP805 to master/single-PMIC mode. */
- ret = axp_write(0xff, 0x0);
+ ret = rsb_init_controller();
if (ret)
return ret;
- ret = axp_check_id();
+ /* Switch to the recommended 3 MHz bus clock. */
+ ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
if (ret)
return ret;
- return 0;
+ /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
+ ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
+ if (ret)
+ return ret;
+
+ /* Associate the 8-bit runtime address with the 12-bit bus address. */
+ ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
+ if (ret)
+ return ret;
+
+ return axp_check_id();
}
int sunxi_pmic_setup(uint16_t socid, const void *fdt)
{
int ret;
- INFO("PMIC: Probing AXP805 on I2C\n");
+ INFO("PMIC: Probing AXP805 on RSB\n");
- ret = sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
+ ret = sunxi_init_platform_r_twi(socid, true);
if (ret)
return ret;
- /* initialise mi2cv driver */
- i2c_init((void *)SUNXI_R_I2C_BASE);
+ ret = rsb_init();
+ if (ret)
+ return ret;
- ret = axp805_probe();
+ /* Switch the AXP805 to master/single-PMIC mode. */
+ ret = axp_write(0xff, 0x0);
if (ret)
return ret;
pmic = AXP805;
axp_setup_regulators(fdt);
+ /* Switch the PMIC back to I2C mode. */
+ ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -96,10 +93,9 @@
{
switch (pmic) {
case AXP805:
- /* Re-initialise after rich OS might have used it. */
- sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
- /* initialise mi2cv driver */
- i2c_init((void *)SUNXI_R_I2C_BASE);
+ /* (Re-)init RSB in case the rich OS has disabled it. */
+ sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
+ rsb_init();
axp_power_off();
break;
default:
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
new file mode 100644
index 0000000..a58b911
--- /dev/null
+++ b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define AFF 00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define POST \
+ };
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x0>;
+ exec_state = <0x0>;
+ load_address = <0x0 0xfd000000>;
+ entrypoint = <0x0 0xfd000000>;
+ binary_size = <0x80000>;
+ };
+
+ /*
+ * temporary: This entry is added based on v2.4 hafnium and will be
+ * removed when rebased to upstream master.
+ */
+ chosen {
+ linux,initrd-start = <0>;
+ linux,initrd-end = <0>;
+ };
+
+ hypervisor {
+ compatible = "hafnium,hafnium";
+ vm1 {
+ is_ffa_partition;
+ debug_name = "op-tee";
+ load_address = <0xfd280000>;
+ };
+ };
+
+ cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
+ CPU_0
+
+ /*
+ * SPMC (Hafnium) requires secondary core nodes are declared
+ * in descending order.
+ */
+ CPU_3
+ CPU_2
+ CPU_1
+ };
+
+ /*
+ * temporary: This device-memory region is added based on v2.4 hafnium
+ * and will be removed when rebased to upstream master. As first
+ * Secure Partition no longer maps device memory.
+ */
+ device-memory@21000000 {
+ device_type = "device-memory";
+ reg = <0x0 0x21000000 0x5f000000>;
+ };
+
+ /* 32MB of TC0_TZC_DRAM1_BASE */
+ memory@fd000000 {
+ device_type = "memory";
+ reg = <0x0 0xfd000000 0x2000000>;
+ };
+};
diff --git a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
index 3df94bf..de5f95d 100644
--- a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
+++ b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
@@ -27,6 +27,12 @@
secure-partitions {
compatible = "arm,sp";
+#if OPTEE_SP_FW_CONFIG
+ op-tee {
+ uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
+ load-address = <0xfd280000>;
+ };
+#else
cactus-primary {
uuid = <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>;
load-address = <0xfe000000>;
@@ -43,5 +49,6 @@
uuid = <0x79b55c73 0x1d8c44b9 0x859361e1 0x770ad8d2>;
load-address = <0xfe200000>;
};
+#endif
};
};
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h
index 72a035f..2ff2699 100644
--- a/plat/arm/board/tc0/include/platform_def.h
+++ b/plat/arm/board/tc0/include/platform_def.h
@@ -112,7 +112,7 @@
* little space for growth.
*/
#if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE 0x1E000
+# define PLAT_ARM_MAX_BL2_SIZE 0x20000
#else
# define PLAT_ARM_MAX_BL2_SIZE 0x14000
#endif
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
index 5d2cc38..6cc5f46 100644
--- a/plat/arm/board/tc0/platform.mk
+++ b/plat/arm/board/tc0/platform.mk
@@ -86,8 +86,12 @@
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
ifeq (${SPD},spmd)
-FDT_SOURCES += ${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts
-TC0_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_spmc_manifest.dtb
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS := ${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS}
+TC0_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TC0_TOS_FW_CONFIG},--tos-fw-config,${TC0_TOS_FW_CONFIG}))
diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc0/tc0_plat.c
index e12ad56..b5698c0 100644
--- a/plat/arm/board/tc0/tc0_plat.c
+++ b/plat/arm/board/tc0/tc0_plat.c
@@ -51,6 +51,10 @@
#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
ARM_MAP_BL1_RW,
#endif
+#ifdef SPD_opteed
+ ARM_MAP_OPTEE_CORE_MEM,
+ ARM_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
{0}
};
#endif
diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c
index 32e124f..9de4a2e 100644
--- a/plat/mediatek/mt8192/bl31_plat_setup.c
+++ b/plat/mediatek/mt8192/bl31_plat_setup.c
@@ -16,6 +16,7 @@
#include <lib/coreboot.h>
/* Platform Includes */
+#include <emi_mpu/emi_mpu.h>
#include <gpio/mtgpio.h>
#include <mt_gic_v3.h>
#include <mt_timer.h>
@@ -89,6 +90,9 @@
ERROR("Failed to set default dcm on!!\n");
}
+ /* MPU Init */
+ emi_mpu_init();
+
/* Initialize the GIC driver, CPU and distributor interfaces */
mt_gic_driver_init();
mt_gic_init();
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..d5d7e2e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <emi_mpu.h>
+#include <lib/mmio.h>
+
+/*
+ * emi_mpu_set_region_protection: protect a region.
+ * @start: start address of the region
+ * @end: end address of the region
+ * @access_permission: EMI MPU access permission
+ * Return 0 for success, otherwise negative status code.
+ */
+static int _emi_mpu_set_protection(
+ unsigned long start, unsigned long end,
+ unsigned int apc)
+{
+ unsigned int dgroup;
+ unsigned int region;
+
+ region = (start >> 24) & 0xFF;
+ start &= 0x00FFFFFF;
+ dgroup = (end >> 24) & 0xFF;
+ end &= 0x00FFFFFF;
+
+ if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+ WARN("Region:%u or dgroup:%u is wrong!\n", region, dgroup);
+ return -1;
+ }
+
+ apc &= 0x80FFFFFF;
+
+ if ((start >= DRAM_OFFSET) && (end >= start)) {
+ start -= DRAM_OFFSET;
+ end -= DRAM_OFFSET;
+ } else {
+ WARN("start:0x%lx or end:0x%lx address is wrong!\n",
+ start, end);
+ return -2;
+ }
+
+ mmio_write_32(EMI_MPU_SA(region), start);
+ mmio_write_32(EMI_MPU_EA(region), end);
+ mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+ return 0;
+}
+
+void dump_emi_mpu_regions(void)
+{
+ unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea;
+
+ int region, i;
+
+ /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
+ for (region = 0; region < 8; ++region) {
+ for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i)
+ apc[i] = mmio_read_32(EMI_MPU_APC(region, i));
+ sa = mmio_read_32(EMI_MPU_SA(region));
+ ea = mmio_read_32(EMI_MPU_EA(region));
+
+ WARN("region %d:\n", region);
+ WARN("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
+ sa, ea, apc[0], apc[1]);
+ }
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+ unsigned long start, end;
+ int i;
+
+ if (region_info->region >= EMI_MPU_REGION_NUM)
+ return -1;
+
+ start = (unsigned long)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+ (region_info->region << 24);
+
+ for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+ end = (unsigned long)(region_info->end >> EMI_MPU_ALIGN_BITS) |
+ (i << 24);
+ _emi_mpu_set_protection(start, end, region_info->apc[i]);
+ }
+
+ return 0;
+}
+
+void emi_mpu_init(void)
+{
+ /* Set permission */
+ struct emi_region_info_t region_info;
+
+ /* PCE-e protect address(TODO) */
+ region_info.start = 0x80000000ULL;
+ region_info.end = 0x83FF0000ULL;
+ region_info.region = 1;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, NO_PROT,
+ NO_PROT /*FORBIDDEN*/);
+ emi_mpu_set_protection(®ion_info);
+
+ /* Forbidden All */
+ region_info.start = 0x40000000ULL; /* dram base addr */
+ region_info.end = 0x1FFFF0000ULL;
+ region_info.region = 2;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+ NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+ NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+ NO_PROT, FORBIDDEN, NO_PROT, NO_PROT);
+ emi_mpu_set_protection(®ion_info);
+
+ dump_emi_mpu_regions();
+}
+
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..0b15431
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define EMI_MPUP (EMI_BASE + 0x01D8)
+#define EMI_MPUQ (EMI_BASE + 0x01E0)
+#define EMI_MPUR (EMI_BASE + 0x01E8)
+#define EMI_MPUS (EMI_BASE + 0x01F0)
+#define EMI_MPUT (EMI_BASE + 0x01F8)
+#define EMI_MPUY (EMI_BASE + 0x0220)
+#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x0000)
+#define EMI_MPUD0_ST (EMI_BASE + 0x0160)
+#define EMI_MPUD1_ST (EMI_BASE + 0x0164)
+#define EMI_MPUD2_ST (EMI_BASE + 0x0168)
+#define EMI_MPUD3_ST (EMI_BASE + 0x016C)
+#define EMI_MPUD0_ST2 (EMI_BASE + 0x0200)
+#define EMI_MPUD1_ST2 (EMI_BASE + 0x0204)
+#define EMI_MPUD2_ST2 (EMI_BASE + 0x0208)
+#define EMI_MPUD3_ST2 (EMI_BASE + 0x020C)
+
+#define EMI_PHY_OFFSET (0x40000000UL)
+
+#define NO_PROT (0)
+#define SEC_RW (1)
+#define SEC_RW_NSEC_R (2)
+#define SEC_RW_NSEC_W (3)
+#define SEC_R_NSEC_R (4)
+#define FORBIDDEN (5)
+#define SEC_R_NSEC_RW (6)
+
+#define SECURE_OS_MPU_REGION_ID (0)
+#define ATF_MPU_REGION_ID (1)
+
+#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region) * 4)
+#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region) * 4)
+
+#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region) * 4 + \
+ (dgroup) * 0x100)
+
+#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + domain * 4)
+#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + domain * 4)
+
+#define EMI_MPU_DOMAIN_NUM 16
+#define EMI_MPU_REGION_NUM 32
+#define EMI_MPU_ALIGN_BITS 16
+#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[0] = 0; \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \
+ | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \
+ | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \
+ | (((unsigned int) d1) << 3) | ((unsigned int) d0) \
+ | (((unsigned int) lock) << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+ d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = \
+ (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) \
+ | (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) \
+ | (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) \
+ | (((unsigned int) d9) << 3) | ((unsigned int) d8); \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \
+ | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \
+ | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \
+ | (((unsigned int) d1) << 3) | ((unsigned int) d0) \
+ | (((unsigned int) lock) << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+ unsigned long long start;
+ unsigned long long end;
+ unsigned int region;
+ unsigned long apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+int emi_mpu_set_protection(struct emi_region_info_t *region_info);
+void dump_emi_mpu_regions(void);
+
+#endif /* __EMI_MPU_H */
diff --git a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
index 053d210..f1d8493 100644
--- a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
+++ b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
@@ -39,15 +39,15 @@
{
unsigned int _core;
- if (core >= PTP3_CFG1_CPU_START_ID) {
- if (core < NR_PTP3_CFG1_CPU) {
- /* update ptp3_cfg1 */
- ptp3_write(
- ptp3_cfg1[core][PTP3_CFG_ADDR],
- ptp3_cfg1[core][PTP3_CFG_VALUE]);
- }
+ /* Apply ptp3_cfg1 for core 0 to 7 */
+ if (core < NR_PTP3_CFG1_CPU) {
+ /* update ptp3_cfg1 */
+ ptp3_write(
+ ptp3_cfg1[core][PTP3_CFG_ADDR],
+ ptp3_cfg1[core][PTP3_CFG_VALUE]);
}
+ /* Apply ptp3_cfg2 for core 4 to 7 */
if (core >= PTP3_CFG2_CPU_START_ID) {
_core = core - PTP3_CFG2_CPU_START_ID;
@@ -59,6 +59,7 @@
}
}
+ /* Apply ptp3_cfg3 for core 4 to 7 */
if (core >= PTP3_CFG3_CPU_START_ID) {
_core = core - PTP3_CFG3_CPU_START_ID;
@@ -73,13 +74,11 @@
void ptp3_deinit(unsigned int core)
{
- if (core >= PTP3_CFG1_CPU_START_ID) {
- if (core < NR_PTP3_CFG1_CPU) {
- /* update ptp3_cfg1 */
- ptp3_write(
- ptp3_cfg1[core][PTP3_CFG_ADDR],
- ptp3_cfg1[core][PTP3_CFG_VALUE] &
- ~PTP3_CFG1_MASK);
- }
+ if (core < NR_PTP3_CFG1_CPU) {
+ /* update ptp3_cfg1 */
+ ptp3_write(
+ ptp3_cfg1[core][PTP3_CFG_ADDR],
+ ptp3_cfg1[core][PTP3_CFG_VALUE] &
+ ~PTP3_CFG1_MASK);
}
}
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.c b/plat/mediatek/mt8192/drivers/rtc/rtc.c
new file mode 100644
index 0000000..124bc8f
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/rtc/rtc.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <rtc.h>
+
+
+static void RTC_Config_Interface(uint32_t addr, uint16_t data,
+ uint16_t mask, uint16_t shift)
+{
+ uint16_t pmic_reg;
+
+ pmic_reg = RTC_Read(addr);
+
+ pmic_reg &= ~(mask << shift);
+ pmic_reg |= (data << shift);
+
+ RTC_Write(addr, pmic_reg);
+}
+
+static int32_t rtc_disable_2sec_reboot(void)
+{
+ uint16_t reboot;
+
+ reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
+ ~RTC_BBPU_AUTO_PDN_SEL;
+ RTC_Write(RTC_AL_SEC, reboot);
+
+ return RTC_Write_Trigger();
+}
+
+static int32_t rtc_enable_k_eosc(void)
+{
+ uint16_t alm_dow, alm_sec;
+ int16_t ret;
+
+ /* Turning on eosc cali mode clock */
+ RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0_CLR, 1,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+ alm_sec = RTC_Read(RTC_AL_SEC) & (~RTC_LPD_OPT_MASK);
+ RTC_Write(RTC_AL_SEC, alm_sec);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_EN);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_RST);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_EN);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
+ RTC_Write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ /* set RTC EOSC calibration period = 8sec */
+ alm_dow = (RTC_Read(RTC_AL_DOW) & (~RTC_RG_EOSC_CALI_TD_MASK)) |
+ RTC_RG_EOSC_CALI_TD_8SEC;
+ RTC_Write(RTC_AL_DOW, alm_dow);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_BBPU,
+ RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ /* Enable K EOSC mode :use solution1 of eosc cali to fix mt6359p 32K*/
+ RTC_Write(RTC_AL_YEA, (((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
+ & (~RTC_K_EOSC_RSV_1)) | (RTC_K_EOSC_RSV_2)));
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ INFO("[RTC] RTC_enable_k_eosc\n");
+
+ return 1;
+}
+
+void rtc_power_off_sequence(void)
+{
+ uint16_t bbpu;
+ int16_t ret;
+
+ ret = rtc_disable_2sec_reboot();
+ if (ret == 0) {
+ return;
+ }
+
+ ret = rtc_enable_k_eosc();
+ if (ret == 0) {
+ return;
+ }
+
+ bbpu = RTC_BBPU_KEY | RTC_BBPU_PWREN;
+
+ if (Writeif_unlock() != 0) {
+ RTC_Write(RTC_BBPU,
+ bbpu | RTC_BBPU_RESET_ALARM | RTC_BBPU_RESET_SPAR);
+ RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return;
+ }
+ mdelay(1);
+
+ bbpu = RTC_Read(RTC_BBPU);
+
+ if (((bbpu & RTC_BBPU_RESET_ALARM) > 0) ||
+ ((bbpu & RTC_BBPU_RESET_SPAR) > 0)) {
+ INFO("[RTC] timeout\n");
+ }
+
+ bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+ RTC_Write(RTC_BBPU, bbpu);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return;
+ }
+ }
+}
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.h b/plat/mediatek/mt8192/drivers/rtc/rtc.h
new file mode 100644
index 0000000..419bfe4
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/rtc/rtc.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+/* RTC registers */
+enum {
+ RTC_BBPU = 0x0588,
+ RTC_IRQ_STA = 0x058A,
+ RTC_IRQ_EN = 0x058C,
+ RTC_CII_EN = 0x058E
+};
+
+enum {
+ RTC_AL_SEC = 0x05A0,
+ RTC_AL_MIN = 0x05A2,
+ RTC_AL_HOU = 0x05A4,
+ RTC_AL_DOM = 0x05A6,
+ RTC_AL_DOW = 0x05A8,
+ RTC_AL_MTH = 0x05AA,
+ RTC_AL_YEA = 0x05AC,
+ RTC_AL_MASK = 0x0590
+};
+
+enum {
+ RTC_OSC32CON = 0x05AE,
+ RTC_CON = 0x05C4,
+ RTC_WRTGR = 0x05C2
+};
+
+enum {
+ RTC_POWERKEY1 = 0x05B0,
+ RTC_POWERKEY2 = 0x05B2
+};
+
+enum {
+ RTC_POWERKEY1_KEY = 0xA357,
+ RTC_POWERKEY2_KEY = 0x67D2
+};
+
+enum {
+ RTC_PDN1 = 0x05B4,
+ RTC_PDN2 = 0x05B6,
+ RTC_SPAR0 = 0x05B8,
+ RTC_SPAR1 = 0x05BA,
+ RTC_PROT = 0x05BC,
+ RTC_DIFF = 0x05BE,
+ RTC_CALI = 0x05C0
+};
+
+enum {
+ RTC_OSC32CON_UNLOCK1 = 0x1A57,
+ RTC_OSC32CON_UNLOCK2 = 0x2B68
+};
+
+enum {
+ RTC_LPD_EN = 0x0406,
+ RTC_LPD_RST = 0x040E
+};
+
+enum {
+ RTC_LPD_OPT_XOSC_AND_EOSC_LPD = 0U << 13,
+ RTC_LPD_OPT_EOSC_LPD = 1U << 13,
+ RTC_LPD_OPT_XOSC_LPD = 2U << 13,
+ RTC_LPD_OPT_F32K_CK_ALIVE = 3U << 13,
+};
+
+#define RTC_LPD_OPT_MASK (3U << 13)
+
+enum {
+ RTC_PROT_UNLOCK1 = 0x586A,
+ RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+ RTC_BBPU_PWREN = 1U << 0,
+ RTC_BBPU_SPAR_SW = 1U << 1,
+ RTC_BBPU_RESET_SPAR = 1U << 2,
+ RTC_BBPU_RESET_ALARM = 1U << 3,
+ RTC_BBPU_CLRPKY = 1U << 4,
+ RTC_BBPU_RELOAD = 1U << 5,
+ RTC_BBPU_CBUSY = 1U << 6
+};
+
+enum {
+ RTC_AL_MASK_SEC = 1U << 0,
+ RTC_AL_MASK_MIN = 1U << 1,
+ RTC_AL_MASK_HOU = 1U << 2,
+ RTC_AL_MASK_DOM = 1U << 3,
+ RTC_AL_MASK_DOW = 1U << 4,
+ RTC_AL_MASK_MTH = 1U << 5,
+ RTC_AL_MASK_YEA = 1U << 6
+};
+
+enum {
+ RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
+ RTC_BBPU_2SEC_CK_SEL = 1U << 7,
+ RTC_BBPU_2SEC_EN = 1U << 8,
+ RTC_BBPU_2SEC_MODE = 0x3 << 9,
+ RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
+ RTC_BBPU_2SEC_STAT_STA = 1U << 12
+};
+
+enum {
+ RTC_BBPU_KEY = 0x43 << 8
+};
+
+enum {
+ RTC_EMBCK_SRC_SEL = 1 << 8,
+ RTC_EMBCK_SEL_MODE = 3 << 6,
+ RTC_XOSC32_ENB = 1 << 5,
+ RTC_REG_XOSC32_ENB = 1 << 15
+};
+
+enum {
+ RTC_K_EOSC_RSV_0 = 1 << 8,
+ RTC_K_EOSC_RSV_1 = 1 << 9,
+ RTC_K_EOSC_RSV_2 = 1 << 10
+};
+
+enum {
+ RTC_RG_EOSC_CALI_TD_1SEC = 3 << 5,
+ RTC_RG_EOSC_CALI_TD_2SEC = 4 << 5,
+ RTC_RG_EOSC_CALI_TD_4SEC = 5 << 5,
+ RTC_RG_EOSC_CALI_TD_8SEC = 6 << 5,
+ RTC_RG_EOSC_CALI_TD_16SEC = 7 << 5,
+ RTC_RG_EOSC_CALI_TD_MASK = 7 << 5
+};
+
+/* PMIC TOP Register Definition */
+enum {
+ PMIC_RG_TOP_CON = 0x0020,
+ PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
+ PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
+ PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
+ PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
+ PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
+ PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
+};
+
+/* PMIC SCK Register Definition */
+enum {
+ PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x0514,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x0516,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x0518,
+ PMIC_RG_EOSC_CALI_CON0 = 0x53A
+};
+
+enum {
+ PMIC_EOSC_CALI_START_ADDR = 0x53A
+};
+
+enum {
+ PMIC_EOSC_CALI_START_MASK = 0x1,
+ PMIC_EOSC_CALI_START_SHIFT = 0
+};
+
+/* PMIC DCXO Register Definition */
+enum {
+ PMIC_RG_DCXO_CW00 = 0x0788,
+ PMIC_RG_DCXO_CW02 = 0x0790,
+ PMIC_RG_DCXO_CW08 = 0x079C,
+ PMIC_RG_DCXO_CW09 = 0x079E,
+ PMIC_RG_DCXO_CW09_CLR = 0x07A2,
+ PMIC_RG_DCXO_CW10 = 0x07A4,
+ PMIC_RG_DCXO_CW12 = 0x07A8,
+ PMIC_RG_DCXO_CW13 = 0x07AA,
+ PMIC_RG_DCXO_CW15 = 0x07AE,
+ PMIC_RG_DCXO_CW19 = 0x07B6,
+};
+
+enum {
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
+ PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
+ PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
+ PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
+ PMIC_RG_XO_EN32K_MAN_SHIFT = 0
+};
+
+/* external API */
+uint16_t RTC_Read(uint32_t addr);
+void RTC_Write(uint32_t addr, uint16_t data);
+int32_t rtc_busy_wait(void);
+int32_t RTC_Write_Trigger(void);
+int32_t Writeif_unlock(void);
+void rtc_power_off_sequence(void);
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/mt8192/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h
index 51cf361..3e44414 100644
--- a/plat/mediatek/mt8192/include/platform_def.h
+++ b/plat/mediatek/mt8192/include/platform_def.h
@@ -30,6 +30,8 @@
#define GPIO_BASE (IO_PHYS + 0x00005000)
#define SPM_BASE (IO_PHYS + 0x00006000)
#define PMIC_WRAP_BASE (IO_PHYS + 0x00026000)
+#define EMI_BASE (IO_PHYS + 0x00219000)
+#define EMI_MPU_BASE (IO_PHYS + 0x00226000)
#define IOCFG_RM_BASE (IO_PHYS + 0x01C20000)
#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000)
#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000)
diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c
index 3ea27b6..6a74c02 100644
--- a/plat/mediatek/mt8192/plat_pm.c
+++ b/plat/mediatek/mt8192/plat_pm.c
@@ -21,6 +21,7 @@
#include <plat_params.h>
#include <plat_pm.h>
#include <pmic.h>
+#include <rtc.h>
/*
* Cluster state request:
@@ -297,10 +298,6 @@
unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
unsigned int cpu = plat_my_core_pos();
- if (aff_lvl > PLAT_MAX_PWR_LVL) {
- return PSCI_E_INVALID_PARAMS;
- }
-
if (pstate == PSTATE_TYPE_STANDBY) {
req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
} else {
@@ -345,6 +342,7 @@
{
INFO("MTK System Off\n");
+ rtc_power_off_sequence();
pmic_power_off();
wfi();
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
index 191895a..a5e7ee2 100644
--- a/plat/mediatek/mt8192/platform.mk
+++ b/plat/mediatek/mt8192/platform.mk
@@ -11,10 +11,12 @@
-I${MTK_PLAT_SOC}/include/ \
-I${MTK_PLAT_SOC}/drivers/ \
-I${MTK_PLAT_SOC}/drivers/dcm \
+ -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
-I${MTK_PLAT_SOC}/drivers/gpio/ \
-I${MTK_PLAT_SOC}/drivers/mcdi/ \
-I${MTK_PLAT_SOC}/drivers/pmic/ \
-I${MTK_PLAT_SOC}/drivers/ptp3/ \
+ -I${MTK_PLAT_SOC}/drivers/rtc/ \
-I${MTK_PLAT_SOC}/drivers/spmc/ \
-I${MTK_PLAT_SOC}/drivers/timer/ \
-I${MTK_PLAT_SOC}/drivers/uart/
@@ -38,6 +40,7 @@
lib/cpus/aarch64/cortex_a76.S \
plat/common/plat_gicv3.c \
${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \
+ ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \
${MTK_PLAT}/common/drivers/uart/uart.c \
${MTK_PLAT}/common/mtk_plat_common.c \
${MTK_PLAT}/common/mtk_sip_svc.c \
@@ -46,6 +49,7 @@
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
${MTK_PLAT_SOC}/bl31_plat_setup.c \
${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
+ ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_topology.c \
${MTK_PLAT_SOC}/plat_mt_gic.c \
@@ -53,6 +57,7 @@
${MTK_PLAT_SOC}/plat_sip_calls.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
+ ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \
diff --git a/plat/ti/k3/board/generic/board.mk b/plat/ti/k3/board/generic/board.mk
index a342214..ef74cd6 100644
--- a/plat/ti/k3/board/generic/board.mk
+++ b/plat/ti/k3/board/generic/board.mk
@@ -13,5 +13,12 @@
K3_HW_CONFIG_BASE ?= 0x82000000
$(eval $(call add_define,K3_HW_CONFIG_BASE))
+# Define sec_proxy usage as the full prioritized communication scheme
+K3_SEC_PROXY_LITE := 0
+$(eval $(call add_define,K3_SEC_PROXY_LITE))
+
+# System coherency is managed in hardware
+USE_COHERENT_MEM := 1
+
PLAT_INCLUDES += \
-Iplat/ti/k3/board/generic/include \
diff --git a/plat/ti/k3/board/lite/board.mk b/plat/ti/k3/board/lite/board.mk
new file mode 100644
index 0000000..76246be
--- /dev/null
+++ b/plat/ti/k3/board/lite/board.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_BASE ?= 0x9e800000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x80080000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x82000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
+
+# Define sec_proxy usage as the lite version
+K3_SEC_PROXY_LITE := 1
+$(eval $(call add_define,K3_SEC_PROXY_LITE))
+
+# We dont have system level coherency capability
+USE_COHERENT_MEM := 0
+
+PLAT_INCLUDES += \
+ -Iplat/ti/k3/board/lite/include \
diff --git a/plat/ti/k3/board/lite/include/board_def.h b/plat/ti/k3/board/lite/include/board_def.h
new file mode 100644
index 0000000..7c7ea62
--- /dev/null
+++ b/plat/ti/k3/board/lite/include/board_def.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_DEF_H
+#define BOARD_DEF_H
+
+#include <lib/utils_def.h>
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT U(4)
+#define K3_CLUSTER1_CORE_COUNT U(0)
+#define K3_CLUSTER2_CORE_COUNT U(0)
+#define K3_CLUSTER3_CORE_COUNT U(0)
+
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ * Current computation assumes data structures necessary for GIC and ARM for
+ * a single cluster of 4 processor.
+ */
+#define SEC_SRAM_BASE 0x70000000 /* Base of SRAM */
+#define SEC_SRAM_SIZE 0x0001a000 /* 104k */
+
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define PLAT_PROC_START_ID 32
+#define PLAT_PROC_DEVICE_START_ID 135
+#define PLAT_CLUSTER_DEVICE_START_ID 134
+
+#endif /* BOARD_DEF_H */
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
index ee1eecf..a0bfdee 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
@@ -97,11 +97,16 @@
.data_end_offset = 0x3C,
},
.threads = {
+#if !K3_SEC_PROXY_LITE
SP_THREAD(SP_NOTIFY),
SP_THREAD(SP_RESPONSE),
SP_THREAD(SP_HIGH_PRIORITY),
SP_THREAD(SP_LOW_PRIORITY),
SP_THREAD(SP_NOTIFY_RESP),
+#else
+ SP_THREAD(SP_RESPONSE),
+ SP_THREAD(SP_HIGH_PRIORITY),
+#endif /* K3_SEC_PROXY_LITE */
},
};
@@ -261,9 +266,14 @@
/*
* 'data_reg' indicates next register to write. If we did not already
* write on tx complete reg(last reg), we must do so for transmit
+ * In addition, we also need to make sure all intermediate data
+ * registers(if any required), are reset to 0 for TISCI backward
+ * compatibility to be maintained.
*/
- if (data_reg <= spm.desc.data_end_offset)
- mmio_write_32(spt->data + spm.desc.data_end_offset, 0);
+ while (data_reg <= spm.desc.data_end_offset) {
+ mmio_write_32(spt->data + data_reg, 0);
+ data_reg += sizeof(uint32_t);
+ }
VERBOSE("Message successfully sent on thread %s\n", spt->name);
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
index 6c4f5df..f4b0b4b 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
@@ -16,13 +16,28 @@
* enum k3_sec_proxy_chan_id - Secure Proxy thread IDs
*
* These the available IDs used in k3_sec_proxy_{send,recv}()
+ * There are two schemes we use:
+ * * if K3_SEC_PROXY_LITE = 1, we just have two threads to talk
+ * * if K3_SEC_PROXY_LITE = 0, we have the full fledged
+ * communication scheme available.
*/
enum k3_sec_proxy_chan_id {
+#if !K3_SEC_PROXY_LITE
SP_NOTIFY = 0,
SP_RESPONSE,
SP_HIGH_PRIORITY,
SP_LOW_PRIORITY,
SP_NOTIFY_RESP,
+#else
+ SP_RESPONSE = 8,
+ /*
+ * Note: TISCI documentation indicates "low priority", but in reality
+ * with a single thread, there is no low or high priority.. This usage
+ * is more appropriate for TF-A since we can reduce the churn as a
+ * result.
+ */
+ SP_HIGH_PRIORITY,
+#endif /* K3_SEC_PROXY_LITE */
};
/**
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
index e390efe..2c3313c 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
@@ -1163,6 +1163,7 @@
ERROR("Message alloc failed (%d)\n", ret);
return ret;
}
+ req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET;
ret = ti_sci_do_xfer(&xfer);
if (ret) {
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
index 2d23f9a..310bf45 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
@@ -95,12 +95,15 @@
/**
* struct ti_sci_msg_req_reboot - Reboot the SoC
* @hdr: Generic Header
+ * @domain: Domain to be reset, 0 for full SoC reboot
*
* Request type is TI_SCI_MSG_SYS_RESET, responded with a generic
* ACK/NACK message.
*/
struct ti_sci_msg_req_reboot {
struct ti_sci_msg_hdr hdr;
+#define TI_SCI_DOMAIN_FULL_SOC_RESET 0x0
+ uint8_t domain;
} __packed;
/**
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
index 8bd7362..ac4e60e 100644
--- a/plat/ti/k3/common/k3_bl31_setup.c
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -13,6 +13,7 @@
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
+#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <k3_console.h>
@@ -23,6 +24,7 @@
const mmap_region_t plat_k3_mmap[] = {
MAP_REGION_FLAT(K3_USART_BASE, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(K3_GIC_BASE, K3_GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(K3_GTC_BASE, K3_GTC_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
@@ -127,6 +129,38 @@
unsigned int plat_get_syscnt_freq2(void)
{
+ uint32_t gtc_freq;
+ uint32_t gtc_ctrl;
+
+ /* Lets try and provide basic diagnostics - cost is low */
+ gtc_ctrl = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTCR_OFFSET);
+ /* Did the bootloader fail to enable timer and OS guys are confused? */
+ if ((gtc_ctrl & K3_GTC_CNTCR_EN_MASK) == 0U) {
+ ERROR("GTC is disabled! Timekeeping broken. Fix Bootloader\n");
+ }
+ /*
+ * If debug will not pause time, we will have issues like
+ * drivers timing out while debugging, in cases of OS like Linux,
+ * RCU stall errors, which can be hard to differentiate vs real issues.
+ */
+ if ((gtc_ctrl & K3_GTC_CNTCR_HDBG_MASK) == 0U) {
+ WARN("GTC: Debug access doesn't stop time. Fix Bootloader\n");
+ }
+
+ gtc_freq = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTFID0_OFFSET);
+ /* Many older bootloaders may have missed programming FID0 register */
+ if (gtc_freq != 0U) {
+ return gtc_freq;
+ }
+
+ /*
+ * We could have just warned about this, but this can have serious
+ * hard to debug side effects if we are NOT sure what the actual
+ * frequency is. Lets make sure people don't miss this.
+ */
+ ERROR("GTC_CNTFID0 is 0! Assuming %d Hz. Fix Bootloader\n",
+ SYS_COUNTER_FREQ_IN_TICKS);
+
return SYS_COUNTER_FREQ_IN_TICKS;
}
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
index c00262b..ab7366b 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/k3/common/plat_common.mk
@@ -11,9 +11,8 @@
# We can choose where a core starts executing
PROGRAMMABLE_RESET_ADDRESS:= 1
-# System coherency is managed in hardware
+# ARM coherency is managed in hardware
WARMBOOT_ENABLE_DCACHE_EARLY := 1
-USE_COHERENT_MEM := 1
# A53 erratum for SoC. (enable them all)
ERRATA_A53_826319 := 1
@@ -21,9 +20,11 @@
ERRATA_A53_836870 := 1
ERRATA_A53_843419 := 1
ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
# A72 Erratum for SoC
ERRATA_A72_859971 := 1
+ERRATA_A72_1319367 := 1
CRASH_REPORTING := 1
HANDLE_EA_EL3_FIRST := 1
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
index 98db626..f12fb0b 100644
--- a/plat/ti/k3/include/platform_def.h
+++ b/plat/ti/k3/include/platform_def.h
@@ -150,15 +150,33 @@
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_EDGE)
+
+#define K3_GTC_BASE 0x00A90000
+/* We just need 20 byte offset, but simpler to just remap the 64K page in */
+#define K3_GTC_SIZE 0x10000
+#define K3_GTC_CNTCR_OFFSET 0x00
+#define K3_GTC_CNTCR_EN_MASK 0x01
+#define K3_GTC_CNTCR_HDBG_MASK 0x02
+#define K3_GTC_CNTFID0_OFFSET 0x20
+
#define K3_GIC_BASE 0x01800000
#define K3_GIC_SIZE 0x200000
+#if !K3_SEC_PROXY_LITE
#define SEC_PROXY_DATA_BASE 0x32C00000
#define SEC_PROXY_DATA_SIZE 0x80000
#define SEC_PROXY_SCFG_BASE 0x32800000
#define SEC_PROXY_SCFG_SIZE 0x80000
#define SEC_PROXY_RT_BASE 0x32400000
#define SEC_PROXY_RT_SIZE 0x80000
+#else
+#define SEC_PROXY_DATA_BASE 0x4D000000
+#define SEC_PROXY_DATA_SIZE 0x80000
+#define SEC_PROXY_SCFG_BASE 0x4A400000
+#define SEC_PROXY_SCFG_SIZE 0x80000
+#define SEC_PROXY_RT_BASE 0x4A600000
+#define SEC_PROXY_RT_SIZE 0x80000
+#endif /* K3_SEC_PROXY_LITE */
#define SEC_PROXY_TIMEOUT_US 1000000
#define SEC_PROXY_MAX_MESSAGE_SIZE 56
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index 4614395..b492210 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -350,4 +350,10 @@
#define AFIFM6_WRCTRL U(13)
#define FABRIC_WIDTH U(3)
+/* CSUDMA Module Base Address*/
+#define CSUDMA_BASE 0xFFC80000
+
+/* RSA-CORE Module Base Address*/
+#define RSA_CORE_BASE 0xFFCE0000
+
#endif /* ZYNQMP_DEF_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index f2dfbb1..0cc517e 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -2446,7 +2446,7 @@
*
* @return Returns success. In case of error, name data is 0.
*/
-enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name)
+void pm_api_clock_get_name(unsigned int clock_id, char *name)
{
if (clock_id == CLK_MAX)
memcpy(name, END_OF_CLK, sizeof(END_OF_CLK) > CLK_NAME_LEN ?
@@ -2458,8 +2458,6 @@
else
memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name,
CLK_NAME_LEN);
-
- return PM_RET_SUCCESS;
}
/**
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
index 301ed24..5efd63f 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -294,7 +294,7 @@
struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id);
uint8_t pm_clock_has_div(unsigned int clock_id, enum pm_clock_div_id div_id);
-enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name);
+void pm_api_clock_get_name(unsigned int clock_id, char *name);
enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks);
enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id,
unsigned int index,
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
index 4b8dfb6..9a6b497 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
@@ -19,39 +19,6 @@
#include "pm_common.h"
#include "pm_ipi.h"
-#define PINCTRL_FUNCTION_MASK U(0xFE)
-#define PINCTRL_VOLTAGE_STATUS_MASK U(0x01)
-#define NFUNCS_PER_PIN U(13)
-#define PINCTRL_NUM_MIOS U(78)
-#define MAX_PIN_PER_REG U(26)
-#define PINCTRL_BANK_ADDR_STEP U(28)
-
-#define PINCTRL_DRVSTRN0_REG_OFFSET U(0)
-#define PINCTRL_DRVSTRN1_REG_OFFSET U(4)
-#define PINCTRL_SCHCMOS_REG_OFFSET U(8)
-#define PINCTRL_PULLCTRL_REG_OFFSET U(12)
-#define PINCTRL_PULLSTAT_REG_OFFSET U(16)
-#define PINCTRL_SLEWCTRL_REG_OFFSET U(20)
-#define PINCTRL_VOLTAGE_STAT_REG_OFFSET U(24)
-
-#define IOU_SLCR_BANK1_CTRL5 U(0XFF180164)
-
-#define PINCTRL_CFG_ADDR_OFFSET(addr, reg, miopin) \
- ((addr) + 4 * PINCTRL_NUM_MIOS + PINCTRL_BANK_ADDR_STEP * \
- ((miopin) / MAX_PIN_PER_REG) + (reg))
-
-#define PINCTRL_PIN_OFFSET(_miopin) \
- ((_miopin) - (MAX_PIN_PER_REG * ((_miopin) / MAX_PIN_PER_REG)))
-
-#define PINCTRL_REGVAL_TO_PIN_CONFIG(_pin, _val) \
- (((_val) >> PINCTRL_PIN_OFFSET(_pin)) & 0x1)
-
-static uint8_t pm_pinctrl_mux[NFUNCS_PER_PIN] = {
- 0x02, 0x04, 0x08, 0x10, 0x18,
- 0x00, 0x20, 0x40, 0x60, 0x80,
- 0xA0, 0xC0, 0xE0
-};
-
struct pinctrl_function {
char name[FUNCTION_NAME_LEN];
uint16_t (*groups)[];
@@ -2604,18 +2571,13 @@
*
* This function is used by master to get name of function specified
* by given function ID.
- *
- * @return Returns success. In case of error, name data is 0.
*/
-enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
- char *name)
+void pm_api_pinctrl_get_function_name(unsigned int fid, char *name)
{
if (fid >= MAX_FUNCTION)
memcpy(name, END_OF_FUNCTION, FUNCTION_NAME_LEN);
else
memcpy(name, pinctrl_functions[fid].name, FUNCTION_NAME_LEN);
-
- return PM_RET_SUCCESS;
}
/**
@@ -2709,333 +2671,6 @@
groups[i] = grps[index + i];
if (groups[i] == (uint16_t)END_OF_GROUPS)
break;
- }
-
- return PM_RET_SUCCESS;
-}
-
-/**
- * pm_api_pinctrl_get_function() - Read function id set for the given pin
- * @pin Pin number
- * @nid Node ID of function currently set for given pin
- *
- * This function provides the function currently set for the given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
- unsigned int *id)
-{
- unsigned int i = 0, j = 0;
- enum pm_ret_status ret = PM_RET_SUCCESS;
- unsigned int ctrlreg, val, gid;
- uint16_t *grps;
-
- ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret != PM_RET_SUCCESS)
- return ret;
-
- val &= PINCTRL_FUNCTION_MASK;
-
- for (i = 0; i < NFUNCS_PER_PIN; i++)
- if (val == pm_pinctrl_mux[i])
- break;
-
- if (i == NFUNCS_PER_PIN)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- gid = *(*zynqmp_pin_groups[pin].groups + i);
-
- for (i = 0; i < MAX_FUNCTION; i++) {
- grps = *pinctrl_functions[i].groups;
- if (grps == NULL)
- continue;
- if (val != pinctrl_functions[i].regval)
- continue;
-
- for (j = 0; grps[j] != (uint16_t)END_OF_GROUPS; j++) {
- if (gid == grps[j]) {
- *id = i;
- goto done;
- }
- }
- }
- if (i == MAX_FUNCTION)
- ret = PM_RET_ERROR_ARGS;
-done:
- return ret;
-}
-
-/**
- * pm_api_pinctrl_set_function() - Set function id set for the given pin
- * @pin Pin number
- * @nid Node ID of function to set for given pin
- *
- * This function provides the function currently set for the given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
- unsigned int fid)
-{
- int i, j;
- unsigned int ctrlreg, val;
- uint16_t *pgrps, *fgrps;
-
- ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
- val = pinctrl_functions[fid].regval;
-
- for (i = 0; i < NFUNCS_PER_PIN; i++)
- if (val == pm_pinctrl_mux[i])
- break;
-
- if (i == NFUNCS_PER_PIN)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- pgrps = *zynqmp_pin_groups[pin].groups;
- if (!pgrps)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- fgrps = *pinctrl_functions[fid].groups;
- if (!fgrps)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- for (i = 0; fgrps[i] != (uint16_t)END_OF_GROUPS; i++)
- for (j = 0; pgrps[j] != (uint16_t)END_OF_GROUPS; j++)
- if (fgrps[i] == pgrps[j])
- goto match;
-
- return PM_RET_ERROR_NOTSUPPORTED;
-
-match:
- return pm_mmio_write(ctrlreg, PINCTRL_FUNCTION_MASK, val);
-}
-
-/**
- * pm_api_pinctrl_set_config() - Set configuration parameter for given pin
- * @pin: Pin for which configuration is to be set
- * @param: Configuration parameter to be set
- * @value: Value to be set for configuration parameter
- *
- * This function sets value of requested configuration parameter for given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
- unsigned int param,
- unsigned int value)
-{
- enum pm_ret_status ret;
- unsigned int ctrlreg, mask, val, offset;
-
- if (param >= PINCTRL_CONFIG_MAX)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- if (pin >= PINCTRL_NUM_MIOS)
- return PM_RET_ERROR_ARGS;
-
- mask = 1 << PINCTRL_PIN_OFFSET(pin);
-
- switch (param) {
- case PINCTRL_CONFIG_SLEW_RATE:
- if (value != PINCTRL_SLEW_RATE_FAST &&
- value != PINCTRL_SLEW_RATE_SLOW)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SLEWCTRL_REG_OFFSET,
- pin);
- val = value << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_BIAS_STATUS:
- if (value != PINCTRL_BIAS_ENABLE &&
- value != PINCTRL_BIAS_DISABLE)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLSTAT_REG_OFFSET,
- pin);
-
- offset = PINCTRL_PIN_OFFSET(pin);
- if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
- offset = (offset < 12U) ?
- (offset + 14U) : (offset - 12U);
-
- val = value << offset;
- mask = 1 << offset;
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_PULL_CTRL:
-
- if (value != PINCTRL_BIAS_PULL_DOWN &&
- value != PINCTRL_BIAS_PULL_UP)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLSTAT_REG_OFFSET,
- pin);
-
- offset = PINCTRL_PIN_OFFSET(pin);
- if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
- offset = (offset < 12U) ?
- (offset + 14U) : (offset - 12U);
-
- val = PINCTRL_BIAS_ENABLE << offset;
- ret = pm_mmio_write(ctrlreg, 1 << offset, val);
- if (ret != PM_RET_SUCCESS)
- return ret;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLCTRL_REG_OFFSET,
- pin);
- val = value << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_SCHMITT_CMOS:
- if (value != PINCTRL_INPUT_TYPE_CMOS &&
- value != PINCTRL_INPUT_TYPE_SCHMITT)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SCHCMOS_REG_OFFSET,
- pin);
-
- val = value << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_DRIVE_STRENGTH:
- if (value > PINCTRL_DRIVE_STRENGTH_12MA)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN0_REG_OFFSET,
- pin);
- val = (value >> 1) << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- if (ret)
- return ret;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN1_REG_OFFSET,
- pin);
- val = (value & 0x01U) << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- default:
- ERROR("Invalid parameter %u\n", param);
- ret = PM_RET_ERROR_NOTSUPPORTED;
- break;
- }
-
- return ret;
-}
-
-/**
- * pm_api_pinctrl_get_config() - Get configuration parameter value for given pin
- * @pin: Pin for which configuration is to be read
- * @param: Configuration parameter to be read
- * @value: buffer to store value of configuration parameter
- *
- * This function reads value of requested configuration parameter for given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
- unsigned int param,
- unsigned int *value)
-{
- enum pm_ret_status ret;
- unsigned int ctrlreg, val;
-
- if (param >= PINCTRL_CONFIG_MAX)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- if (pin >= PINCTRL_NUM_MIOS)
- return PM_RET_ERROR_ARGS;
-
- switch (param) {
- case PINCTRL_CONFIG_SLEW_RATE:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SLEWCTRL_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret != PM_RET_SUCCESS)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_BIAS_STATUS:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLSTAT_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
- val = ((val & 0x3FFF) << 12) | ((val >> 14) & 0xFFF);
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_PULL_CTRL:
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLCTRL_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_SCHMITT_CMOS:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SCHCMOS_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_DRIVE_STRENGTH:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN0_REG_OFFSET,
- pin);
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val) << 1;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN1_REG_OFFSET,
- pin);
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value |= PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_VOLTAGE_STATUS:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_VOLTAGE_STAT_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = val & PINCTRL_VOLTAGE_STATUS_MASK;
- break;
- default:
- return PM_RET_ERROR_NOTSUPPORTED;
}
return PM_RET_SUCCESS;
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
index 9923c00..2b8fca3 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -709,18 +709,7 @@
#define PINCTRL_DRIVE_STRENGTH_8MA 2U
#define PINCTRL_DRIVE_STRENGTH_12MA 3U
-enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
- unsigned int fid);
-enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
- unsigned int *id);
-enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
- unsigned int param,
- unsigned int value);
-enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
- unsigned int param,
- unsigned int *value);
-enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
- char *name);
+void pm_api_pinctrl_get_function_name(unsigned int fid, char *name);
enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid,
unsigned int index,
uint16_t *groups);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index cd9d597..9a53408 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -65,6 +65,10 @@
PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \
}
+#define EM_PACK_PAYLOAD1(pl, arg0) { \
+ pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
+}
+
/**
* pm_self_suspend() - PM call for processor to suspend itself
* @nid Node id of the processor or subsystem
@@ -655,7 +659,11 @@
*/
enum pm_ret_status pm_pinctrl_request(unsigned int pin)
{
- return PM_RET_SUCCESS;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
@@ -668,37 +676,44 @@
*/
enum pm_ret_status pm_pinctrl_release(unsigned int pin)
{
- return PM_RET_SUCCESS;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
* pm_pinctrl_get_function() - Read function id set for the given pin
* @pin Pin number
- * @nid Node ID of function currently set for given pin
+ * @fid ID of function currently set for given pin
*
* This function provides the function currently set for the given pin.
*
* @return Returns status, either success or error+reason
*/
-enum pm_ret_status pm_pinctrl_get_function(unsigned int pin,
- enum pm_node_id *nid)
+enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid)
{
- return pm_api_pinctrl_get_function(pin, nid);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin);
+ return pm_ipi_send_sync(primary_proc, payload, fid, 1);
}
/**
* pm_pinctrl_set_function() - Set function id set for the given pin
* @pin Pin number
- * @nid Node ID of function to set for given pin
- *
- * This function provides the function currently set for the given pin.
+ * @fid ID of function to set for given pin
*
* @return Returns status, either success or error+reason
*/
-enum pm_ret_status pm_pinctrl_set_function(unsigned int pin,
- enum pm_node_id nid)
+enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid)
{
- return pm_api_pinctrl_set_function(pin, (unsigned int)nid);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
@@ -715,24 +730,30 @@
unsigned int param,
unsigned int *value)
{
- return pm_api_pinctrl_get_config(pin, param, value);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
}
/**
- * pm_pinctrl_set_config() - Read value of requested config param for given pin
+ * pm_pinctrl_set_config() - Set value of requested config param for given pin
* @pin Pin number
* @param Parameter to set
* @value Parameter value to set
*
- * This function provides the configuration parameter value for the given pin.
- *
* @return Returns status, either success or error+reason
*/
enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
unsigned int param,
unsigned int value)
{
- return pm_api_pinctrl_set_config(pin, param, value);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param,
+ value);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
@@ -793,12 +814,10 @@
*
* This function is used by master to get nmae of clock specified
* by given clock ID.
- *
- * @return Returns status, either success or error+reason
*/
-static enum pm_ret_status pm_clock_get_name(unsigned int clock_id, char *name)
+static void pm_clock_get_name(unsigned int clock_id, char *name)
{
- return pm_api_clock_get_name(clock_id, name);
+ pm_api_clock_get_name(clock_id, name);
}
/**
@@ -1235,13 +1254,10 @@
*
* This function is used by master to get name of function specified
* by given function Id
- *
- * Return: Returns status, either success or error+reason.
*/
-static enum pm_ret_status pm_pinctrl_get_function_name(unsigned int fid,
- char *name)
+static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
{
- return pm_api_pinctrl_get_function_name(fid, name);
+ pm_api_pinctrl_get_function_name(fid, name);
}
/**
@@ -1301,78 +1317,58 @@
* @data Returned output data
*
* This function returns requested data.
- *
- * @return Returns status, either success or error+reason
*/
-enum pm_ret_status pm_query_data(enum pm_query_id qid,
- unsigned int arg1,
- unsigned int arg2,
- unsigned int arg3,
- unsigned int *data)
+void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
+ unsigned int arg3, unsigned int *data)
{
- enum pm_ret_status ret;
-
switch (qid) {
case PM_QID_CLOCK_GET_NAME:
- ret = pm_clock_get_name(arg1, (char *)data);
+ pm_clock_get_name(arg1, (char *)data);
break;
case PM_QID_CLOCK_GET_TOPOLOGY:
- ret = pm_clock_get_topology(arg1, arg2, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
break;
case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
- ret = pm_clock_get_fixedfactor_params(arg1, &data[1], &data[2]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
+ &data[2]);
break;
case PM_QID_CLOCK_GET_PARENTS:
- ret = pm_clock_get_parents(arg1, arg2, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
break;
case PM_QID_CLOCK_GET_ATTRIBUTES:
- ret = pm_clock_get_attributes(arg1, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_attributes(arg1, &data[1]);
break;
case PM_QID_PINCTRL_GET_NUM_PINS:
- ret = pm_pinctrl_get_num_pins(&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_num_pins(&data[1]);
break;
case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
- ret = pm_pinctrl_get_num_functions(&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_num_functions(&data[1]);
break;
case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
- ret = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
break;
case PM_QID_PINCTRL_GET_FUNCTION_NAME:
- ret = pm_pinctrl_get_function_name(arg1, (char *)data);
+ pm_pinctrl_get_function_name(arg1, (char *)data);
break;
case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
- ret = pm_pinctrl_get_function_groups(arg1, arg2,
- (uint16_t *)&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
break;
case PM_QID_PINCTRL_GET_PIN_GROUPS:
- ret = pm_pinctrl_get_pin_groups(arg1, arg2,
- (uint16_t *)&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
break;
case PM_QID_CLOCK_GET_NUM_CLOCKS:
- ret = pm_clock_get_num_clocks(&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_num_clocks(&data[1]);
break;
case PM_QID_CLOCK_GET_MAX_DIVISOR:
- ret = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
break;
default:
- ret = PM_RET_ERROR_ARGS;
+ data[0] = PM_RET_ERROR_ARGS;
WARN("Unimplemented query service call: 0x%x\n", qid);
- break;
}
-
- return ret;
}
enum pm_ret_status pm_sha_hash(uint32_t address_high,
@@ -1554,3 +1550,101 @@
PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
return pm_ipi_send_sync(primary_proc, payload, mode, 1);
}
+
+/**
+ * pm_register_access() - PM API for register read/write access data
+ *
+ * @register_access_id Register_access_id which says register read/write
+ *
+ * @address Address of the register to be accessed
+ *
+ * @mask Mask value to be used while writing value
+ *
+ * @value Value to be written to register
+ *
+ * @out Returned output data
+ *
+ * This function returns requested data.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_access(unsigned int register_access_id,
+ unsigned int address,
+ unsigned int mask,
+ unsigned int value,
+ unsigned int *out)
+{
+ enum pm_ret_status ret;
+
+ if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
+ ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
+ ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
+ ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE))
+ return PM_RET_ERROR_ACCESS;
+
+ switch (register_access_id) {
+ case CONFIG_REG_WRITE:
+ ret = pm_mmio_write(address, mask, value);
+ break;
+ case CONFIG_REG_READ:
+ ret = pm_mmio_read(address, out);
+ break;
+ default:
+ ret = PM_RET_ERROR_ARGS;
+ WARN("Unimplemented register_access call\n\r");
+ }
+ return ret;
+}
+
+/**
+ * pm_efuse_access() - To program or read efuse bits.
+ *
+ * This function provides access to the xilskey library to program/read
+ * efuse bits.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * value: Returned output value
+ *
+ * @return Returns status, either success or error+reason
+ *
+ */
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
+
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_set_action(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_remove_action(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_send_errors(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index ff66d3f..b0c2652 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -28,6 +28,11 @@
PM_QID_CLOCK_GET_MAX_DIVISOR,
};
+enum pm_register_access_id {
+ CONFIG_REG_WRITE,
+ CONFIG_REG_READ,
+};
+
/**********************************************************
* System-level API function declarations
**********************************************************/
@@ -151,11 +156,8 @@
unsigned int parent_id);
enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
unsigned int *parent_id);
-enum pm_ret_status pm_query_data(enum pm_query_id qid,
- unsigned int arg1,
- unsigned int arg2,
- unsigned int arg3,
- unsigned int *data);
+void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
+ unsigned int arg3, unsigned int *data);
enum pm_ret_status pm_sha_hash(uint32_t address_high,
uint32_t address_low,
uint32_t size,
@@ -178,6 +180,11 @@
enum pm_ret_status pm_aes_engine(uint32_t address_high,
uint32_t address_low,
uint32_t *value);
+enum pm_ret_status pm_register_access(unsigned int register_access_id,
+ unsigned int address,
+ unsigned int mask,
+ unsigned int value,
+ unsigned int *out);
enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
enum pm_pll_param param_id,
@@ -189,5 +196,10 @@
enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+ uint32_t address_low, uint32_t *value);
+enum pm_ret_status em_set_action(unsigned int *value);
+enum pm_ret_status em_remove_action(unsigned int *value);
+enum pm_ret_status em_send_errors(unsigned int *value);
#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index 4776d42..ee31c92 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -33,6 +33,7 @@
#define PM_STATE_CPU_IDLE 0x0U
#define PM_STATE_SUSPEND_TO_RAM 0xFU
+#define EM_FUNID_NUM_MASK 0xF0000U
/*********************************************************************
* Enum definitions
********************************************************************/
@@ -97,6 +98,9 @@
PM_PLL_GET_PARAMETER,
PM_PLL_SET_MODE,
PM_PLL_GET_MODE,
+ /* PM Register Access API */
+ PM_REGISTER_ACCESS,
+ PM_EFUSE_ACCESS,
PM_API_MAX
};
@@ -320,4 +324,13 @@
PM_CLOCK_DIV1_ID,
};
+/**
+ * EM API IDs
+ */
+enum em_api_id {
+ EM_SET_ACTION = 1,
+ EM_REMOVE_ACTION,
+ EM_SEND_ERRORS,
+};
+
#endif /* PM_DEFS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index 3f4f069..a4bc1ac 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -474,8 +474,8 @@
{
uint32_t data[4] = { 0 };
- ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
- pm_arg[3], data);
+ pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], data);
SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32),
(uint64_t)data[2] | ((uint64_t)data[3] << 32));
}
@@ -606,8 +606,78 @@
SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32));
}
+ case PM_REGISTER_ACCESS:
+ {
+ uint32_t value;
+
+ ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_EFUSE_ACCESS:
+ {
+ uint32_t value;
+
+ ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
}
}
+
+/**
+ * em_smc_handler() - SMC handler for EM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return - Unused
+ *
+ * Determines that smc_fid is valid and supported EM SMC Function ID from the
+ * list of em_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for EM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+ enum pm_ret_status ret;
+
+ switch (smc_fid & FUNCID_NUM_MASK) {
+ /* EM API Functions */
+ case EM_SET_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_set_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case EM_REMOVE_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_remove_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case EM_SEND_ERRORS:
+ {
+ uint32_t value;
+
+ ret = em_send_errors(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ default:
+ WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
index 0968f64..abadd40 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,4 +14,7 @@
uint64_t x4, void *cookie, void *handle,
uint64_t flags);
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle,
+ uint64_t flags);
#endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c
index 9b18274..4c29da2 100644
--- a/plat/xilinx/zynqmp/sip_svc_setup.c
+++ b/plat/xilinx/zynqmp/sip_svc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +25,9 @@
#define PM_FID_MASK 0xf000u
#define PM_FID_VALUE 0u
#define IPI_FID_VALUE 0x1000u
+#define EM_FID_MASK 0xf0000u
+#define EM_FID_VALUE 0xE0000u
+#define is_em_fid(_fid) (((_fid) & EM_FID_MASK) == EM_FID_VALUE)
#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE)
@@ -61,8 +64,12 @@
void *handle,
u_register_t flags)
{
+ /* Let EM SMC handler deal with EM-related requests */
+ if (is_em_fid(smc_fid)) {
+ return em_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ } else if (is_pm_fid(smc_fid)) {
/* Let PM SMC handler deal with PM-related requests */
- if (is_pm_fid(smc_fid)) {
return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
flags);
}