Merge pull request #1700 from jwerner-chromium/JW_crashfix
MULTI_CONSOLE_API fixes and cleanups
diff --git a/acknowledgements.rst b/acknowledgements.rst
index 4d527f4..095b5ad 100644
--- a/acknowledgements.rst
+++ b/acknowledgements.rst
@@ -1,3 +1,9 @@
+**Note: This file is only relevant for legacy contributions, to acknowledge the
+specific contributors referred to in "Arm Limited and Contributors" copyright
+notices. As contributors are now encouraged to put their name or company name
+directly into the copyright notices, this file is not relevant for new
+contributions.**
+
Contributor Acknowledgements
============================
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 54db681..77bd63e 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -356,24 +356,8 @@
* We already have x0-x4 in place. x5 will point to a cookie (not used
* now). x6 will point to the context structure (SP_EL3) and x7 will
* contain flags we need to pass to the handler.
- *
- * Save x4-x29 and sp_el0.
*/
- stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
- stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
- stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
- stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
- stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
- stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
- stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
- stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
- stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
- stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
- stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
- stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
- stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
- mrs x18, sp_el0
- str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0]
+ bl save_gp_registers
mov x5, xzr
mov x6, sp
diff --git a/contributing.rst b/contributing.rst
index 5ab7f09..d98d5b9 100644
--- a/contributing.rst
+++ b/contributing.rst
@@ -50,19 +50,19 @@
other in-source documentation needs updating.
- Ensure that each changed file has the correct copyright and license
information. Files that entirely consist of contributions to this
- project should have the copyright notice and BSD-3-Clause SPDX license
- identifier as shown in `license.rst`_. Files that contain
- changes to imported Third Party IP should contain a notice as follows,
- with the original copyright and license text retained:
+ project should have a copyright notice and BSD-3-Clause SPDX license
+ identifier of the form as shown in `license.rst`_. Files that contain
+ changes to imported Third Party IP files should retain their original
+ copyright and license notices. For significant contributions you may
+ add your own copyright notice in following format:
::
- Portions copyright (c) [XXXX-]YYYY, Arm Limited and Contributors. All rights reserved.
+ Portions copyright (c) [XXXX-]YYYY, <OWNER>. All rights reserved.
where XXXX is the year of first contribution (if different to YYYY) and
- YYYY is the year of most recent contribution.
- - If not done previously, you may add your name or your company name to
- the `Acknowledgements`_ file.
+ YYYY is the year of most recent contribution. <OWNER> is your name or
+ your company name.
- If you are submitting new files that you intend to be the technical
sub-maintainer for (for example, a new platform port), then also update
the `Maintainers`_ file.
diff --git a/docs/marvell/build.txt b/docs/marvell/build.txt
index 8a669c1..0682b77 100644
--- a/docs/marvell/build.txt
+++ b/docs/marvell/build.txt
@@ -78,9 +78,11 @@
Supported Options:
- DDR3 1CS (0): DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB)
- DDR4 1CS (1): DB-88F3720-DDR4-Modular (512MB)
- - DDR3 2CS (2): EspressoBIN (1GB)
+ - DDR3 2CS (2): EspressoBIN V3-V5 (1GB)
- DDR4 2CS (3): DB-88F3720-DDR4-Modular (4GB)
- DDR3 1CS (4): DB-88F3720-DDR3-Modular (1GB)
+ - DDR4 1CS (5): EspressoBin V7 (1GB)
+ - DDR4 2CS (6): EspressoBin V7 (2GB)
- CUSTOMER (CUST): Customer board, DDR3 1CS 512MB
- CLOCKSPRESET: For Armada37x0 only, the clock tree configuration preset including CPU and DDR frequency,
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
new file mode 100644
index 0000000..ab33a8a
--- /dev/null
+++ b/docs/plat/imx8m.rst
@@ -0,0 +1,42 @@
+Description
+===========
+
+The i.MX 8M family of applications processors based on Arm Corte-A53 and Cortex-M4
+cores provide high-performance computing, power efficiency, enhanced system
+reliability and embedded security needed to drive the growth of fast-growing
+edge node computing, streaming multimedia, and machine learning applications.
+
+Boot Sequence
+=============
+
+Bootrom --> SPL --> BL31 --> BL33(u-boot) --> Linux kernel
+
+How to build
+============
+
+Build Procedure
+---------------
+
+- Prepare AARCH64 toolchain.
+
+- Build spl and u-boot firstly, and get binary images: u-boot-spl.bin,
+ u-boot-nodtb.bin and dtb for the target board.
+
+- Build TF-A
+
+ Build bl31:
+
+ .. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=<Target_SoC> bl31
+
+ Target_SoC should be "imx8mq" for i.MX8MQ SoC.
+
+Deploy TF-A Images
+-----------------
+
+TF-A binary(bl31.bin), u-boot-spl.bin u-boot-nodtb.bin and dtb are combined
+together to generate a binary file called flash.bin, the imx-mkimage tool is
+used to generate flash.bin, and flash.bin needs to be flashed into SD card
+with certain offset for BOOT ROM. the u-boot and imx-mkimage will be upstreamed
+soon, this doc will be updated once they are ready, and the link will be posted.
diff --git a/drivers/arm/ccn/ccn.c b/drivers/arm/ccn/ccn.c
index 910cd7c..59a7576 100644
--- a/drivers/arm/ccn/ccn.c
+++ b/drivers/arm/ccn/ccn.c
@@ -11,6 +11,7 @@
#include <debug.h>
#include <errno.h>
#include <mmio.h>
+#include <stdbool.h>
#include "ccn_private.h"
static const ccn_desc_t *ccn_plat_desc;
@@ -490,3 +491,123 @@
return (int)(mmio_read_64(periphbase
+ MN_PERIPH_ID_0_1_OFFSET) & 0xFF);
}
+
+/*******************************************************************************
+ * This function returns the region id corresponding to a node_id of node_type.
+ ******************************************************************************/
+static unsigned int get_region_id_for_node(node_types_t node_type,
+ unsigned int node_id)
+{
+ unsigned int mn_reg_off, region_id;
+ unsigned long long node_bitmap;
+ unsigned int loc_node_id, node_pos_in_map = 0;
+
+ assert(node_type < NUM_NODE_TYPES);
+ assert(node_id < MAX_RN_NODES);
+
+ switch (node_type) {
+ case NODE_TYPE_RNI:
+ region_id = RNI_REGION_ID_START;
+ break;
+ case NODE_TYPE_HNF:
+ region_id = HNF_REGION_ID_START;
+ break;
+ case NODE_TYPE_HNI:
+ region_id = HNI_REGION_ID_START;
+ break;
+ case NODE_TYPE_SN:
+ region_id = SBSX_REGION_ID_START;
+ break;
+ default:
+ ERROR("Un-supported Node Type = %d.\n", node_type);
+ assert(false);
+ return REGION_ID_LIMIT;
+ }
+ /*
+ * RN-I, HN-F, HN-I, SN node registers in the MN region
+ * occupy contiguous 16 byte apart offsets.
+ *
+ * RN-F and RN-D node are not supported as
+ * none of them exposes any memory map to
+ * configure any of their offset registers.
+ */
+
+ mn_reg_off = MN_RNF_NODEID_OFFSET + (node_type << 4);
+ node_bitmap = ccn_reg_read(ccn_plat_desc->periphbase,
+ MN_REGION_ID, mn_reg_off);
+
+ assert((node_bitmap & (1ULL << (node_id))) != 0U);
+
+
+ FOR_EACH_PRESENT_NODE_ID(loc_node_id, node_bitmap) {
+ INFO("Index = %u with loc_nod=%u and input nod=%u\n",
+ node_pos_in_map, loc_node_id, node_id);
+ if (loc_node_id == node_id)
+ break;
+ node_pos_in_map++;
+ }
+
+ if (node_pos_in_map == CCN_MAX_RN_MASTERS) {
+ ERROR("Node Id = %d, is not found.\n", node_id);
+ assert(false);
+ return REGION_ID_LIMIT;
+ }
+
+ region_id += node_pos_in_map;
+
+ return region_id;
+}
+
+/*******************************************************************************
+ * This function sets the value 'val' to the register at register_offset from
+ * the base address pointed to by the region_id.
+ * where, region id is mapped to a node_id of node_type.
+ ******************************************************************************/
+void ccn_write_node_reg(node_types_t node_type, unsigned int node_id,
+ unsigned int reg_offset, unsigned long long val)
+{
+ unsigned int region_id = get_region_id_for_node(node_type, node_id);
+
+ if (reg_offset > REGION_ID_OFFSET) {
+ ERROR("Invalid Register offset 0x%x is provided.\n",
+ reg_offset);
+ assert(false);
+ return;
+ }
+
+ /* Setting the value of Auxilary Control Register of the Node */
+ ccn_reg_write(ccn_plat_desc->periphbase, region_id, reg_offset, val);
+ VERBOSE("Value is successfully written at address 0x%lx.\n",
+ (ccn_plat_desc->periphbase
+ + region_id_to_base(region_id))
+ + reg_offset);
+}
+
+/*******************************************************************************
+ * This function read the value 'val' stored in the register at register_offset
+ * from the base address pointed to by the region_id.
+ * where, region id is mapped to a node_id of node_type.
+ ******************************************************************************/
+unsigned long long ccn_read_node_reg(node_types_t node_type,
+ unsigned int node_id,
+ unsigned int reg_offset)
+{
+ unsigned long long val;
+ unsigned int region_id = get_region_id_for_node(node_type, node_id);
+
+ if (reg_offset > REGION_ID_OFFSET) {
+ ERROR("Invalid Register offset 0x%x is provided.\n",
+ reg_offset);
+ assert(false);
+ return ULL(0);
+ }
+
+ /* Setting the value of Auxilary Control Register of the Node */
+ val = ccn_reg_read(ccn_plat_desc->periphbase, region_id, reg_offset);
+ VERBOSE("Value is successfully read from address 0x%lx.\n",
+ (ccn_plat_desc->periphbase
+ + region_id_to_base(region_id))
+ + reg_offset);
+
+ return val;
+}
diff --git a/drivers/arm/tzc/tzc380.c b/drivers/arm/tzc/tzc380.c
new file mode 100644
index 0000000..082161f
--- /dev/null
+++ b/drivers/arm/tzc/tzc380.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stddef.h>
+#include <tzc380.h>
+
+struct tzc380_instance {
+ uintptr_t base;
+ uint8_t addr_width;
+ uint8_t num_regions;
+};
+
+struct tzc380_instance tzc380;
+
+static unsigned int tzc380_read_build_config(uintptr_t base)
+{
+ return mmio_read_32(base + TZC380_CONFIGURATION_OFF);
+}
+
+static void tzc380_write_action(uintptr_t base, tzc_action_t action)
+{
+ mmio_write_32(base + ACTION_OFF, action);
+}
+
+static void tzc380_write_region_base_low(uintptr_t base, unsigned int region,
+ unsigned int val)
+{
+ mmio_write_32(base + REGION_SETUP_LOW_OFF(region), val);
+}
+
+static void tzc380_write_region_base_high(uintptr_t base, unsigned int region,
+ unsigned int val)
+{
+ mmio_write_32(base + REGION_SETUP_HIGH_OFF(region), val);
+}
+
+static void tzc380_write_region_attributes(uintptr_t base, unsigned int region,
+ unsigned int val)
+{
+ mmio_write_32(base + REGION_ATTRIBUTES_OFF(region), val);
+}
+
+void tzc380_init(uintptr_t base)
+{
+ unsigned int tzc_build;
+
+ assert(base != 0U);
+ tzc380.base = base;
+
+ /* Save values we will use later. */
+ tzc_build = tzc380_read_build_config(tzc380.base);
+ tzc380.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
+ BUILD_CONFIG_AW_MASK) + 1;
+ tzc380.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
+ BUILD_CONFIG_NR_MASK) + 1;
+}
+
+static uint32_t addr_low(uintptr_t addr)
+{
+ return (uint32_t)addr;
+}
+
+static uint32_t addr_high(uintptr_t addr __unused)
+{
+#if (UINTPTR_MAX == UINT64_MAX)
+ return addr >> 32;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * `tzc380_configure_region` is used to program regions into the TrustZone
+ * controller.
+ */
+void tzc380_configure_region(uint8_t region, uintptr_t region_base, unsigned int attr)
+{
+ assert(tzc380.base != 0U);
+
+ assert(region < tzc380.num_regions);
+
+ tzc380_write_region_base_low(tzc380.base, region, addr_low(region_base));
+ tzc380_write_region_base_high(tzc380.base, region, addr_high(region_base));
+ tzc380_write_region_attributes(tzc380.base, region, attr);
+}
+
+void tzc380_set_action(tzc_action_t action)
+{
+ assert(tzc380.base != 0U);
+
+ /*
+ * - Currently no handler is provided to trap an error via interrupt
+ * or exception.
+ * - The interrupt action has not been tested.
+ */
+ tzc380_write_action(tzc380.base, action);
+}
diff --git a/drivers/marvell/ap807_clocks_init.c b/drivers/marvell/ap807_clocks_init.c
new file mode 100644
index 0000000..841e6ae
--- /dev/null
+++ b/drivers/marvell/ap807_clocks_init.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <aro.h>
+#include <delay_timer.h>
+#include <mmio.h>
+
+/* Notify bootloader on DRAM setup */
+#define AP807_CPU_ARO_CTRL(cluster) \
+ (MVEBU_RFU_BASE + 0x82A8 + (0xA58 * (cluster)))
+
+/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
+#define AP807_CPU_ARO_CLK_EN_OFFSET 0
+#define AP807_CPU_ARO_CLK_EN_MASK (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
+
+/* 0 - ARO is the clock source, 1 - PLL is the clock source */
+#define AP807_CPU_ARO_SEL_PLL_OFFSET 5
+#define AP807_CPU_ARO_SEL_PLL_MASK (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
+
+/* AP807 clusters count */
+#define AP807_CLUSTER_NUM 2
+
+/* PLL frequency values */
+#define PLL_FREQ_1200 0x2AE5F002 /* 1200 */
+#define PLL_FREQ_2000 0x2FC9F002 /* 2000 */
+#define PLL_FREQ_2200 0x2AC57001 /* 2200 */
+#define PLL_FREQ_2400 0x2AE5F001 /* 2400 */
+
+/* CPU PLL control registers */
+#define AP807_CPU_PLL_CTRL(cluster) \
+ (MVEBU_RFU_BASE + 0x82E0 + (0x8 * (cluster)))
+
+#define AP807_CPU_PLL_PARAM(cluster) AP807_CPU_PLL_CTRL(cluster)
+#define AP807_CPU_PLL_CFG(cluster) (AP807_CPU_PLL_CTRL(cluster) + 0x4)
+#define AP807_CPU_PLL_CFG_BYPASS_MODE (0x1)
+#define AP807_CPU_PLL_CFG_USE_REG_FILE (0x1 << 9)
+
+static void pll_set_freq(unsigned int freq_val)
+{
+ int i;
+
+ for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+ mmio_write_32(AP807_CPU_PLL_CFG(i),
+ AP807_CPU_PLL_CFG_USE_REG_FILE);
+ mmio_write_32(AP807_CPU_PLL_CFG(i),
+ AP807_CPU_PLL_CFG_USE_REG_FILE |
+ AP807_CPU_PLL_CFG_BYPASS_MODE);
+ mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val);
+ mmio_write_32(AP807_CPU_PLL_CFG(i),
+ AP807_CPU_PLL_CFG_USE_REG_FILE);
+ }
+}
+
+/* Switch to ARO from PLL in ap807 */
+static void aro_to_pll(void)
+{
+ unsigned int reg;
+ int i;
+
+ for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+ /* switch from ARO to PLL */
+ reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+ reg |= AP807_CPU_ARO_SEL_PLL_MASK;
+ mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+
+ mdelay(100);
+
+ /* disable ARO clk driver */
+ reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+ reg |= (AP807_CPU_ARO_CLK_EN_MASK);
+ mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+ }
+}
+
+/* switch from ARO to PLL
+ * in case of default frequency option, configure PLL registers
+ * to be aligned with new default frequency.
+ */
+void ap807_clocks_init(unsigned int freq_option)
+{
+ /* Switch from ARO to PLL */
+ aro_to_pll();
+
+ /* Modifications in frequency table:
+ * 0x0: 764x: change to 2000 MHz.
+ * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400.
+ * 0x3: 3900/744x/764x change to 1200 MHz.
+ */
+ switch (freq_option) {
+ case CPU_2000_DDR_1200_RCLK_1200:
+ pll_set_freq(PLL_FREQ_2000);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h
index 78c7a38..e3b430a 100644
--- a/drivers/marvell/comphy/phy-comphy-common.h
+++ b/drivers/marvell/comphy/phy-comphy-common.h
@@ -18,13 +18,15 @@
#endif
/* A lane is described by 4 fields:
- * - bit 1~0 represent comphy polarity invert
- * - bit 7~2 represent comphy speed
- * - bit 11~8 represent unit index
- * - bit 16~12 represent mode
- * - bit 17 represent comphy indication of clock source
- * - bit 19-18 represents pcie width (in case of pcie comphy config.)
- * - bit 31~20 reserved
+ * - bit 1~0 represent comphy polarity invert
+ * - bit 7~2 represent comphy speed
+ * - bit 11~8 represent unit index
+ * - bit 16~12 represent mode
+ * - bit 17 represent comphy indication of clock source
+ * - bit 20~18 represents pcie width (in case of pcie comphy config.)
+ * - bit 21 represents the source of the request (Linux/Bootloader),
+ * (reguired only for PCIe!)
+ * - bit 31~22 reserved
*/
#define COMPHY_INVERT_OFFSET 0
@@ -50,6 +52,11 @@
#define COMPHY_PCI_WIDTH_LEN 3
#define COMPHY_PCI_WIDTH_MASK COMPHY_MASK(COMPHY_PCI_WIDTH_OFFSET, \
COMPHY_PCI_WIDTH_LEN)
+#define COMPHY_PCI_CALLER_OFFSET \
+ (COMPHY_PCI_WIDTH_OFFSET + COMPHY_PCI_WIDTH_LEN)
+#define COMPHY_PCI_CALLER_LEN 1
+#define COMPHY_PCI_CALLER_MASK COMPHY_MASK(COMPHY_PCI_CALLER_OFFSET, \
+ COMPHY_PCI_CALLER_LEN)
#define COMPHY_MASK(offset, len) (((1 << (len)) - 1) << (offset))
@@ -69,6 +76,10 @@
#define COMPHY_GET_PCIE_WIDTH(x) (((x) & COMPHY_PCI_WIDTH_MASK) >> \
COMPHY_PCI_WIDTH_OFFSET)
+/* Macro which extracts the caller for pcie power on from lane description */
+#define COMPHY_GET_CALLER(x) (((x) & COMPHY_PCI_CALLER_MASK) >> \
+ COMPHY_PCI_CALLER_OFFSET)
+
/* Macro which extracts the polarity invert from lane description */
#define COMPHY_GET_POLARITY_INVERT(x) (((x) & COMPHY_INVERT_MASK) >> \
COMPHY_INVERT_OFFSET)
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 25893a9..86e5f1c 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -208,8 +208,8 @@
*/
if ((mode == COMPHY_SGMII_MODE ||
mode == COMPHY_HS_SGMII_MODE ||
- mode == COMPHY_SFI_MODE) &&
- COMPHY_GET_ID(comphy_mode) == 1)
+ mode == COMPHY_SFI_MODE || mode == COMPHY_XFI_MODE)
+ && COMPHY_GET_ID(comphy_mode) == 1)
reg |= COMMON_SELECTOR_COMPHY4_PORT1 <<
comphy_offset;
else
@@ -1205,6 +1205,22 @@
uint32_t clk_dir;
uintptr_t hpipe_addr, comphy_addr, addr;
_Bool clk_src = COMPHY_GET_CLK_SRC(comphy_mode);
+ _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
+
+ /* In Armada 8K DB boards, PCIe initialization can be executed
+ * only once (PCIe reset performed during chip power on and
+ * it cannot be executed via GPIO later).
+ * This means that power on can be executed only once, so let's
+ * mark if the caller is bootloader or Linux.
+ * If bootloader -> run power on.
+ * If Linux -> exit.
+ *
+ * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
+ * so after GPIO reset is added to Linux Kernel, it can be
+ * powered-on by Linux.
+ */
+ if (!called_from_uboot)
+ return ret;
hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
comphy_index);
@@ -2366,14 +2382,45 @@
return err;
}
-int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index)
+int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index,
+ uint64_t comphy_mode)
{
uintptr_t sd_ip_addr, comphy_ip_addr;
uint32_t mask, data;
uint8_t ap_nr, cp_nr;
+ _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
debug_enter();
+ /* Power-off might happen because of 2 things:
+ * 1. Bootloader turns off unconnected lanes
+ * 2. Linux turns off all lanes during boot
+ * (and then reconfigure it).
+ *
+ * For PCIe, there's a problem:
+ * In Armada 8K DB boards, PCIe initialization can be executed
+ * only once (PCIe reset performed during chip power on and
+ * it cannot be executed via GPIO later) so a lane configured to
+ * PCIe should not be powered off by Linux.
+ *
+ * So, check 2 things:
+ * 1. Is Linux called for power-off?
+ * 2. Is the comphy configured to PCIe?
+ * If the answer is YES for both 1 and 2, skip the power-off.
+ *
+ * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
+ * so after GPIO reset is added to Linux Kernel, it can be
+ * powered-off.
+ */
+ if (!called_from_uboot) {
+ data = mmio_read_32(comphy_base +
+ COMMON_SELECTOR_PIPE_REG_OFFSET);
+ data >>= (COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index);
+ data &= COMMON_SELECTOR_COMPHY_MASK;
+ if (data == COMMON_SELECTOR_PIPE_COMPHY_PCIE)
+ return 0;
+ }
+
mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) {
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.h b/drivers/marvell/comphy/phy-comphy-cp110.h
index 70dbfbf..407909b 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.h
+++ b/drivers/marvell/comphy/phy-comphy-cp110.h
@@ -82,7 +82,7 @@
int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base,
uint8_t comphy_index);
int mvebu_cp110_comphy_power_off(uint64_t comphy_base,
- uint8_t comphy_index);
+ uint8_t comphy_index, uint64_t comphy_mode);
int mvebu_cp110_comphy_power_on(uint64_t comphy_base,
uint8_t comphy_index, uint64_t comphy_mode);
int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 418ab11..4160003 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -246,6 +246,13 @@
return ret;
}
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return ret;
+ }
+ } while (ret != MMC_STATE_TRAN);
+
nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) |
(mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) |
(mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) |
@@ -379,7 +386,10 @@
int ret, n;
unsigned int resp_data[4];
- mmc_reset_to_idle();
+ ret = mmc_reset_to_idle();
+ if (ret != 0) {
+ return ret;
+ };
for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) {
ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE |
@@ -409,7 +419,10 @@
ops->init();
- mmc_reset_to_idle();
+ ret = mmc_reset_to_idle();
+ if (ret != 0) {
+ return ret;
+ };
if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
ret = mmc_send_op_cond();
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 633a425..db51581 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -97,7 +97,7 @@
#define SDMMC_STAR_CMDSENT BIT(7)
#define SDMMC_STAR_DATAEND BIT(8)
#define SDMMC_STAR_DBCKEND BIT(10)
-#define SDMMC_STAR_DPSMACT BIT(11)
+#define SDMMC_STAR_DPSMACT BIT(12)
#define SDMMC_STAR_RXFIFOHF BIT(15)
#define SDMMC_STAR_RXFIFOE BIT(19)
#define SDMMC_STAR_IDMATE BIT(27)
@@ -266,21 +266,22 @@
mmio_write_32(base + SDMMC_CMDR, cmd_reg);
+ status = mmio_read_32(base + SDMMC_STAR);
+
start = get_timer(0);
- do {
- status = mmio_read_32(base + SDMMC_STAR);
-
+ while ((status & flags_cmd) == 0U) {
if (get_timer(start) > TIMEOUT_10_MS) {
err = -ETIMEDOUT;
ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
__func__, cmd->cmd_idx, status);
- break;
+ goto err_exit;
}
- } while ((status & flags_cmd) == 0U);
- if (((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) &&
- (err == 0)) {
+ status = mmio_read_32(base + SDMMC_STAR);
+ }
+
+ if ((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) {
if ((status & SDMMC_STAR_CTIMEOUT) != 0U) {
err = -ETIMEDOUT;
/*
@@ -300,9 +301,11 @@
ERROR("%s: CRCFAIL (cmd = %d,status = %x)\n",
__func__, cmd->cmd_idx, status);
}
+
+ goto err_exit;
}
- if (((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) && (err == 0)) {
+ if ((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) {
if ((cmd->cmd_idx == MMC_CMD(9)) &&
((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) {
/* Need to invert response to match CSD structure */
@@ -324,32 +327,26 @@
}
}
- if ((flags_data == 0U) || (err != 0)) {
- if (flags_data != 0U) {
- mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS);
- }
-
+ if (flags_data == 0U) {
mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
- if ((err != 0) && (flags_data != 0U)) {
- return stm32_sdmmc2_stop_transfer();
- }
-
- return err;
+ return 0;
}
+ status = mmio_read_32(base + SDMMC_STAR);
+
start = get_timer(0);
- do {
- status = mmio_read_32(base + SDMMC_STAR);
-
+ while ((status & flags_data) == 0U) {
if (get_timer(start) > TIMEOUT_10_MS) {
ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
__func__, cmd->cmd_idx, status);
err = -ETIMEDOUT;
- break;
+ goto err_exit;
}
- } while ((status & flags_data) == 0U);
+
+ status = mmio_read_32(base + SDMMC_STAR);
+ };
if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL |
SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR |
@@ -359,11 +356,16 @@
err = -EIO;
}
+err_exit:
mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS);
if (err != 0) {
- return stm32_sdmmc2_stop_transfer();
+ int ret_stop = stm32_sdmmc2_stop_transfer();
+
+ if (ret_stop != 0) {
+ return ret_stop;
+ }
}
return err;
diff --git a/include/drivers/arm/ccn.h b/include/drivers/arm/ccn.h
index eba974d..9c3abac 100644
--- a/include/drivers/arm/ccn.h
+++ b/include/drivers/arm/ccn.h
@@ -76,6 +76,16 @@
uintptr_t periphbase;
} ccn_desc_t;
+/* Enum used to loop through all types of nodes in CCN*/
+typedef enum node_types {
+ NODE_TYPE_RNF = 0,
+ NODE_TYPE_RNI,
+ NODE_TYPE_RND,
+ NODE_TYPE_HNF,
+ NODE_TYPE_HNI,
+ NODE_TYPE_SN,
+ NUM_NODE_TYPES
+} node_types_t;
void ccn_init(const ccn_desc_t *plat_ccn_desc);
void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map);
@@ -92,5 +102,12 @@
unsigned int ccn_get_l3_run_mode(void);
int ccn_get_part0_id(uintptr_t periphbase);
+void ccn_write_node_reg(node_types_t node_type, unsigned int node_id,
+ unsigned int reg_offset,
+ unsigned long long val);
+unsigned long long ccn_read_node_reg(node_types_t node_type,
+ unsigned int node_id,
+ unsigned int reg_offset);
+
#endif /* __ASSEMBLY__ */
#endif /* CCN_H */
diff --git a/include/drivers/arm/tzc380.h b/include/drivers/arm/tzc380.h
new file mode 100644
index 0000000..19cf988
--- /dev/null
+++ b/include/drivers/arm/tzc380.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TZC380_H
+#define TZC380_H
+
+#include <tzc_common.h>
+#include <utils_def.h>
+
+#define TZC380_CONFIGURATION_OFF U(0x000)
+#define ACTION_OFF U(0x004)
+#define LOCKDOWN_RANGE_OFF U(0x008)
+#define LOCKDOWN_SELECT_OFF U(0x00C)
+#define INT_STATUS U(0x010)
+#define INT_CLEAR U(0x014)
+
+#define FAIL_ADDRESS_LOW_OFF U(0x020)
+#define FAIL_ADDRESS_HIGH_OFF U(0x024)
+#define FAIL_CONTROL_OFF U(0x028)
+#define FAIL_ID U(0x02c)
+
+#define SPECULATION_CTRL_OFF U(0x030)
+#define SECURITY_INV_EN_OFF U(0x034)
+
+#define REGION_SETUP_LOW_OFF(n) U(0x100 + (n) * 0x10)
+#define REGION_SETUP_HIGH_OFF(n) U(0x104 + (n) * 0x10)
+#define REGION_ATTRIBUTES_OFF(n) U(0x108 + (n) * 0x10)
+
+#define BUILD_CONFIG_AW_SHIFT 8
+#define BUILD_CONFIG_AW_MASK U(0x3f)
+#define BUILD_CONFIG_NR_SHIFT 0
+#define BUILD_CONFIG_NR_MASK U(0xf)
+
+#define ACTION_RV_SHIFT 0
+#define ACTION_RV_MASK U(0x3)
+#define ACTION_RV_LOWOK U(0x0)
+#define ACTION_RV_LOWERR U(0x1)
+#define ACTION_RV_HIGHOK U(0x2)
+#define ACTION_RV_HIGHERR U(0x3)
+
+/* Speculation is enabled by default. */
+#define SPECULATION_CTRL_WRITE_DISABLE BIT_32(1)
+#define SPECULATION_CTRL_READ_DISABLE BIT_32(0)
+
+#define INT_STATUS_OVERRUN_SHIFT 1
+#define INT_STATUS_OVERRUN_MASK U(0x1)
+#define INT_STATUS_STATUS_SHIFT 0
+#define INT_STATUS_STATUS_MASK U(0x1)
+
+#define INT_CLEAR_CLEAR_SHIFT 0
+#define INT_CLEAR_CLEAR_MASK U(0x1)
+
+#define TZC380_COMPONENT_ID U(0xb105f00d)
+#define TZC380_PERIPH_ID_LOW U(0x001bb380)
+#define TZC380_PERIPH_ID_HIGH U(0x00000004)
+
+#define TZC_SP_NS_W BIT_32(0)
+#define TZC_SP_NS_R BIT_32(1)
+#define TZC_SP_S_W BIT_32(2)
+#define TZC_SP_S_R BIT_32(3)
+
+#define TZC_ATTR_SP_SHIFT 28
+#define TZC_ATTR_SP_ALL ((TZC_SP_S_W | TZC_SP_S_R | TZC_SP_NS_W | \
+ TZC_SP_NS_R) << TZC_ATTR_SP_SHIFT)
+#define TZC_ATTR_SP_S_RW ((TZC_SP_S_W | TZC_SP_S_R) << \
+ TZC_ATTR_SP_SHIFT)
+#define TZC_ATTR_SP_NS_RW ((TZC_SP_NS_W | TZC_SP_NS_R) << \
+ TZC_ATTR_SP_SHIFT)
+
+#define TZC_REGION_SIZE_32K U(0xe)
+#define TZC_REGION_SIZE_64K U(0xf)
+#define TZC_REGION_SIZE_128K U(0x10)
+#define TZC_REGION_SIZE_256K U(0x11)
+#define TZC_REGION_SIZE_512K U(0x12)
+#define TZC_REGION_SIZE_1M U(0x13)
+#define TZC_REGION_SIZE_2M U(0x14)
+#define TZC_REGION_SIZE_4M U(0x15)
+#define TZC_REGION_SIZE_8M U(0x16)
+#define TZC_REGION_SIZE_16M U(0x17)
+#define TZC_REGION_SIZE_32M U(0x18)
+#define TZC_REGION_SIZE_64M U(0x19)
+#define TZC_REGION_SIZE_128M U(0x1a)
+#define TZC_REGION_SIZE_256M U(0x1b)
+#define TZC_REGION_SIZE_512M U(0x1c)
+#define TZC_REGION_SIZE_1G U(0x1d)
+#define TZC_REGION_SIZE_2G U(0x1e)
+#define TZC_REGION_SIZE_4G U(0x1f)
+#define TZC_REGION_SIZE_8G U(0x20)
+#define TZC_REGION_SIZE_16G U(0x21)
+#define TZC_REGION_SIZE_32G U(0x22)
+#define TZC_REGION_SIZE_64G U(0x23)
+#define TZC_REGION_SIZE_128G U(0x24)
+#define TZC_REGION_SIZE_256G U(0x25)
+#define TZC_REGION_SIZE_512G U(0x26)
+#define TZC_REGION_SIZE_1T U(0x27)
+#define TZC_REGION_SIZE_2T U(0x28)
+#define TZC_REGION_SIZE_4T U(0x29)
+#define TZC_REGION_SIZE_8T U(0x2a)
+#define TZC_REGION_SIZE_16T U(0x2b)
+#define TZC_REGION_SIZE_32T U(0x2c)
+#define TZC_REGION_SIZE_64T U(0x2d)
+#define TZC_REGION_SIZE_128T U(0x2e)
+#define TZC_REGION_SIZE_256T U(0x2f)
+#define TZC_REGION_SIZE_512T U(0x30)
+#define TZC_REGION_SIZE_1P U(0x31)
+#define TZC_REGION_SIZE_2P U(0x32)
+#define TZC_REGION_SIZE_4P U(0x33)
+#define TZC_REGION_SIZE_8P U(0x34)
+#define TZC_REGION_SIZE_16P U(0x35)
+#define TZC_REGION_SIZE_32P U(0x36)
+#define TZC_REGION_SIZE_64P U(0x37)
+#define TZC_REGION_SIZE_128P U(0x38)
+#define TZC_REGION_SIZE_256P U(0x39)
+#define TZC_REGION_SIZE_512P U(0x3a)
+#define TZC_REGION_SIZE_1E U(0x3b)
+#define TZC_REGION_SIZE_2E U(0x3c)
+#define TZC_REGION_SIZE_4E U(0x3d)
+#define TZC_REGION_SIZE_8E U(0x3e)
+#define TZC_REGION_SIZE_16E U(0x3f)
+
+#define TZC_REGION_SIZE_SHIFT 0x1
+#define TZC_REGION_SIZE_MASK U(0x7e)
+#define TZC_ATTR_REGION_SIZE(s) ((s) << TZC_REGION_SIZE_SHIFT)
+
+#define TZC_ATTR_REGION_EN_SHIFT 0x0
+#define TZC_ATTR_REGION_EN_MASK U(0x1)
+
+#define TZC_ATTR_REGION_EN
+#define TZC_ATTR_REGION_ENABLE U(0x1)
+#define TZC_ATTR_REGION_DISABLE U(0x0)
+
+#define REGION_MAX 16
+
+void tzc380_init(uintptr_t base);
+void tzc380_configure_region(uint8_t region,
+ uintptr_t region_base,
+ unsigned int attr);
+void tzc380_set_action(tzc_action_t action);
+static inline void tzc_init(uintptr_t base)
+{
+ tzc380_init(base);
+}
+
+static inline void tzc_configure_region(uint8_t region,
+ uintptr_t region_base,
+ unsigned int attr)
+{
+ tzc380_configure_region(region, region_base, attr);
+}
+
+static inline void tzc_set_action(tzc_action_t action)
+{
+ tzc380_set_action(action);
+}
+
+#endif /* TZC380_H */
diff --git a/include/drivers/marvell/ap807_clocks_init.h b/include/drivers/marvell/ap807_clocks_init.h
new file mode 100644
index 0000000..4353b83
--- /dev/null
+++ b/include/drivers/marvell/ap807_clocks_init.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef AP807_INIT_CLOCKS_H
+#define AP807_INIT_CLOCKS_H
+
+void ap807_clocks_init(unsigned int freq_option);
+
+#endif /* AP807_INIT_CLOCKS_H */
+
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 02963ac..2b48967 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -162,4 +162,11 @@
#define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory")
+/* Compiler builtin of GCC >= 9 and planned in llvm */
+#ifdef __HAVE_SPECULATION_SAFE_VALUE
+# define SPECULATION_SAFE_VALUE(var) __builtin_speculation_safe_value(var)
+#else
+# define SPECULATION_SAFE_VALUE(var) var
+#endif
+
#endif /* UTILS_DEF_H */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index d02a405..cbac247 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -34,6 +34,7 @@
#define ARM_PWR_LVL0 MPIDR_AFFLVL0
#define ARM_PWR_LVL1 MPIDR_AFFLVL1
#define ARM_PWR_LVL2 MPIDR_AFFLVL2
+#define ARM_PWR_LVL3 MPIDR_AFFLVL3
/*
* Macros for local power states in ARM platforms encoded by State-ID field
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index eeb72de..ff75c69 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -11,9 +11,6 @@
#include <psci.h>
#include <stdint.h>
-/* System power domain at level 2, as currently implemented by CSS platforms */
-#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
-
/* Macros to read the CSS power domain state */
#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0]
#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1]
diff --git a/lib/psci/psci_stat.c b/lib/psci/psci_stat.c
index 421db44..6f6a7d4 100644
--- a/lib/psci/psci_stat.c
+++ b/lib/psci/psci_stat.c
@@ -206,9 +206,9 @@
if (pwrlvl > PSCI_CPU_PWR_LVL) {
/* Get the power domain index */
- parent_idx = psci_cpu_pd_nodes[target_idx].parent_node;
+ parent_idx = SPECULATION_SAFE_VALUE(psci_cpu_pd_nodes[target_idx].parent_node);
for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl < pwrlvl; lvl++)
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
+ parent_idx = SPECULATION_SAFE_VALUE(psci_non_cpu_pd_nodes[parent_idx].parent_node);
/* Get the non cpu power domain stats */
*psci_stat = psci_non_cpu_stat[parent_idx][stat_idx];
diff --git a/license.rst b/license.rst
index a4464d9..29bdf56 100644
--- a/license.rst
+++ b/license.rst
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
+Copyright (c) [XXXX-]YYYY, <OWNER>. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 7b85043..78d3025 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -416,3 +416,8 @@
.read_mem_protect = arm_psci_read_mem_protect,
.write_mem_protect = arm_nor_psci_write_mem_protect,
};
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return ops;
+}
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 0bbe3e1..8098bc3 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -295,4 +295,7 @@
#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c
new file mode 100644
index 0000000..da2e92b
--- /dev/null
+++ b/plat/arm/board/juno/juno_pm.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_arm.h>
+#include <scmi.h>
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index ba1acd4..ad955f6 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -27,6 +27,7 @@
CSS_USE_SCMI_SDS_DRIVER := 1
PLAT_INCLUDES := -Iplat/arm/board/juno/include \
+ -Iplat/arm/css/drivers/scmi \
-Iplat/arm/css/drivers/sds
PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/${ARCH}/juno_helpers.S \
@@ -79,6 +80,7 @@
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
lib/utils/mem_region.c \
+ plat/arm/board/juno/juno_pm.c \
plat/arm/board/juno/juno_topology.c \
plat/arm/common/arm_nor_psci_mem_protect.c \
${JUNO_GIC_SOURCES} \
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
index 5278109..b3471c1 100644
--- a/plat/arm/board/juno/sp_min/sp_min-juno.mk
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -10,6 +10,7 @@
lib/cpus/aarch32/cortex_a57.S \
lib/cpus/aarch32/cortex_a72.S \
lib/utils/mem_region.c \
+ plat/arm/board/juno/juno_pm.c \
plat/arm/board/juno/juno_topology.c \
plat/arm/common/arm_nor_psci_mem_protect.c \
plat/arm/soc/common/soc_css_security.c \
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
index 3e48397..fa639ca 100644
--- a/plat/arm/board/n1sdp/include/platform_def.h
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -32,6 +32,8 @@
N1SDP_MAX_CPUS_PER_CLUSTER * \
N1SDP_MAX_PE_PER_CPU)
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
/*
* PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index 65aad9c..cdd0b63 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -6,6 +6,7 @@
#include "../../css/drivers/scmi/scmi.h"
#include "../../css/drivers/mhu/css_mhu_doorbell.h"
+#include <plat_arm.h>
#include <platform_def.h>
static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
@@ -20,3 +21,8 @@
{
return &n1sdp_scmi_plat_info;
}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/sgi575/fdts/sgi575.dts b/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts
similarity index 100%
rename from plat/arm/board/sgi575/fdts/sgi575.dts
rename to plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts
diff --git a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
index 315fa69..b14d7ad 100644
--- a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
+++ b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
@@ -9,8 +9,8 @@
/ {
/* Platform Config */
compatible = "arm,tb_fw";
- hw_config_addr = <0x0 0xFEF00000>;
- hw_config_max_size = <0x0100000>;
+ nt_fw_config_addr = <0x0 0xFEF00000>;
+ nt_fw_config_max_size = <0x0100000>;
/*
* The following two entries are placeholders for Mbed TLS
* heap information. The default values don't matter since
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index c06a0a1..16e2898 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -20,4 +20,9 @@
#define SGI575_DMC620_BASE0 UL(0x4e000000)
#define SGI575_DMC620_BASE1 UL(0x4e100000)
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index dd82d29..e72225d 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -14,12 +14,14 @@
BL1_SOURCES += ${SGI_CPU_SOURCES}
-BL2_SOURCES += ${SGI575_BASE}/sgi575_security.c \
+BL2_SOURCES += ${SGI575_BASE}/sgi575_plat.c \
+ ${SGI575_BASE}/sgi575_security.c \
drivers/arm/tzc/tzc_dmc620.c \
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${SGI575_BASE}/sgi575_plat.c \
drivers/cfi/v2m/v2m_flash.c \
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
@@ -31,8 +33,8 @@
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
-FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}.dts
-HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb
+FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
-# Add the HW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
diff --git a/plat/arm/board/sgi575/sgi575_plat.c b/plat/arm/board/sgi575/sgi575_plat.c
new file mode 100644
index 0000000..a8ca916
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_plat.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT)
+ & SSC_VERSION_CONFIG_MASK;
+}
diff --git a/plat/arm/board/sgiclarka/fdts/sgiclarka.dts b/plat/arm/board/sgiclarka/fdts/sgiclarka_nt_fw_config.dts
similarity index 100%
rename from plat/arm/board/sgiclarka/fdts/sgiclarka.dts
rename to plat/arm/board/sgiclarka/fdts/sgiclarka_nt_fw_config.dts
diff --git a/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts b/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts
index 315fa69..b14d7ad 100644
--- a/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts
+++ b/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts
@@ -9,8 +9,8 @@
/ {
/* Platform Config */
compatible = "arm,tb_fw";
- hw_config_addr = <0x0 0xFEF00000>;
- hw_config_max_size = <0x0100000>;
+ nt_fw_config_addr = <0x0 0xFEF00000>;
+ nt_fw_config_max_size = <0x0100000>;
/*
* The following two entries are placeholders for Mbed TLS
* heap information. The default values don't matter since
diff --git a/plat/arm/board/sgiclarka/include/platform_def.h b/plat/arm/board/sgiclarka/include/platform_def.h
index ba6d043..39907e8 100644
--- a/plat/arm/board/sgiclarka/include/platform_def.h
+++ b/plat/arm/board/sgiclarka/include/platform_def.h
@@ -20,4 +20,9 @@
#define SGICLARKA_DMC620_BASE0 UL(0x4e000000)
#define SGICLARKA_DMC620_BASE1 UL(0x4e100000)
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgiclarka/platform.mk b/plat/arm/board/sgiclarka/platform.mk
index cf02219..1a8b157 100644
--- a/plat/arm/board/sgiclarka/platform.mk
+++ b/plat/arm/board/sgiclarka/platform.mk
@@ -14,12 +14,14 @@
BL1_SOURCES += ${SGI_CPU_SOURCES}
-BL2_SOURCES += ${SGICLARKA_BASE}/sgiclarka_security.c \
+BL2_SOURCES += ${SGICLARKA_BASE}/sgiclarka_plat.c \
+ ${SGICLARKA_BASE}/sgiclarka_security.c \
drivers/arm/tzc/tzc_dmc620.c \
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${SGICLARKA_BASE}/sgiclarka_plat.c \
drivers/cfi/v2m/v2m_flash.c \
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
@@ -31,10 +33,10 @@
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
-FDT_SOURCES += ${SGICLARKA_BASE}/fdts/${PLAT}.dts
-HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb
+FDT_SOURCES += ${SGICLARKA_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
-# Add the HW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
override CTX_INCLUDE_AARCH32_REGS := 0
diff --git a/plat/arm/board/sgiclarka/sgiclarka_plat.c b/plat/arm/board/sgiclarka/sgiclarka_plat.c
new file mode 100644
index 0000000..3df2da6
--- /dev/null
+++ b/plat/arm/board/sgiclarka/sgiclarka_plat.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+ & SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 6394bfb..3be1b5d 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -14,7 +14,6 @@
#include <psci.h>
/* Allow ARM Standard platforms to override these functions */
-#pragma weak plat_arm_psci_override_pm_ops
#pragma weak plat_arm_program_trusted_mailbox
#if !ARM_RECOM_STATE_ID_ENC
@@ -133,14 +132,6 @@
}
/******************************************************************************
- * Default definition on ARM standard platforms to override the plat_psci_ops.
- *****************************************************************************/
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
-{
- return ops;
-}
-
-/******************************************************************************
* Helper function to save the platform state before a system suspend. Save the
* state of the system components which are not in the Always ON power domain.
*****************************************************************************/
diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h
index e1358bf..28dfc9a 100644
--- a/plat/arm/css/drivers/scmi/scmi.h
+++ b/plat/arm/css/drivers/scmi/scmi.h
@@ -8,6 +8,7 @@
#define SCMI_H
#include <bakery_lock.h>
+#include <psci.h>
#include <stddef.h>
#include <stdint.h>
#include <spinlock.h>
@@ -162,4 +163,7 @@
/* API to get the platform specific SCMI channel information. */
scmi_channel_plat_info_t *plat_css_get_scmi_info();
+/* API to override default PSCI callbacks for platforms that support SCMI. */
+const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops);
+
#endif /* SCMI_H */
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index 956f583..1397fd8 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -339,7 +339,7 @@
* the SCMI driver, query capability via SCMI and modify the PSCI capability
* based on that.
*****************************************************************************/
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops)
{
uint32_t msg_attr;
int ret;
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 1395373..8705d63 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -119,8 +119,6 @@
#define PLAT_ARM_NSRAM_BASE 0x06000000
#define PLAT_ARM_NSRAM_SIZE 0x00080000 /* 512KB */
-#define PLAT_MAX_PWR_LVL U(1)
-
#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp)
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
index dea580b..56dc334 100644
--- a/plat/arm/css/sgi/include/sgi_variant.h
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -21,4 +21,10 @@
extern sgi_platform_info_t sgi_plat_info;
+/* returns the part number of the platform*/
+unsigned int plat_arm_sgi_get_platform_id(void);
+
+/* returns the configuration id of the platform */
+unsigned int plat_arm_sgi_get_config_id(void);
+
#endif /* SGI_VARIANT_H */
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index ce85026..a254388 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -42,53 +42,11 @@
panic();
};
-/*******************************************************************************
- * This function sets the sgi_platform_id and sgi_config_id
- ******************************************************************************/
-int sgi_identify_platform(unsigned long hw_config)
-{
- void *fdt;
- int nodeoffset;
- const unsigned int *property;
-
- fdt = (void *)hw_config;
-
- /* Check the validity of the fdt */
- assert(fdt_check_header(fdt) == 0);
-
- nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
- if (nodeoffset < 0) {
- ERROR("Failed to get system-id node offset\n");
- return -1;
- }
-
- property = fdt_getprop(fdt, nodeoffset, "platform-id", NULL);
- if (property == NULL) {
- ERROR("Failed to get platform-id property\n");
- return -1;
- }
-
- sgi_plat_info.platform_id = fdt32_to_cpu(*property);
-
- property = fdt_getprop(fdt, nodeoffset, "config-id", NULL);
- if (property == NULL) {
- ERROR("Failed to get config-id property\n");
- return -1;
- }
-
- sgi_plat_info.config_id = fdt32_to_cpu(*property);
-
- return 0;
-}
-
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
- int ret;
-
- ret = sgi_identify_platform(arg2);
- if (ret == -1)
- panic();
+ sgi_plat_info.platform_id = plat_arm_sgi_get_platform_id();
+ sgi_plat_info.config_id = plat_arm_sgi_get_config_id();
arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
}
@@ -101,3 +59,8 @@
sgi_ras_intr_handler_setup();
#endif
}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c
index d97583e..e078bd2 100644
--- a/plat/arm/css/sgi/sgi_image_load.c
+++ b/plat/arm/css/sgi/sgi_image_load.c
@@ -9,6 +9,7 @@
#include <desc_image_load.h>
#include <libfdt.h>
#include <platform.h>
+#include <sgi_variant.h>
/*******************************************************************************
* This function inserts Platform information via device tree nodes as,
@@ -23,11 +24,10 @@
void *fdt;
int nodeoffset, err;
unsigned int platid = 0, platcfg = 0;
- char *platform_name;
- mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
+ mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
if (mem_params == NULL) {
- ERROR("HW CONFIG base address is NULL");
+ ERROR("NT_FW CONFIG base address is NULL");
return -1;
}
@@ -35,27 +35,7 @@
/* Check the validity of the fdt */
if (fdt_check_header(fdt) != 0) {
- ERROR("Invalid HW_CONFIG DTB passed\n");
- return -1;
- }
-
- platform_name = (char *)fdt_getprop(fdt, 0, "compatible", NULL);
-
- if (platform_name == NULL) {
- ERROR("Invalid HW_CONFIG DTB passed\n");
- return -1;
- }
-
- if (strcmp(platform_name, "arm,sgi575") == 0) {
- platid = mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK;
- platcfg = (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT)
- & SSC_VERSION_CONFIG_MASK;
- } else if (strcmp(platform_name, "arm,sgi-clark") == 0) {
- platid = mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
- & SID_SYSTEM_ID_PART_NUM_MASK;
- platcfg = mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
- } else {
- WARN("Invalid platform\n");
+ ERROR("Invalid NT_FW_CONFIG DTB passed\n");
return -1;
}
@@ -65,12 +45,14 @@
return -1;
}
+ platid = plat_arm_sgi_get_platform_id();
err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid);
if (err < 0) {
ERROR("Failed to set platform-id\n");
return -1;
}
+ platcfg = plat_arm_sgi_get_config_id();
err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg);
if (err < 0) {
ERROR("Failed to set config-id\n");
diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c
index 3b7a57a..e524f11 100644
--- a/plat/arm/css/sgi/sgi_topology.c
+++ b/plat/arm/css/sgi/sgi_topology.c
@@ -44,3 +44,11 @@
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
};
+
+/******************************************************************************
+ * Return the number of PE's supported by the CPU.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+ return CSS_SGI_MAX_PE_PER_CPU;
+}
diff --git a/plat/arm/css/sgm/include/sgm_base_platform_def.h b/plat/arm/css/sgm/include/sgm_base_platform_def.h
index a9795a4..2178f06 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -239,4 +239,8 @@
*/
#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \
V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+
#endif /* SGM_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgm/sgm_bl31_setup.c b/plat/arm/css/sgm/sgm_bl31_setup.c
index 29c32e7..952572e 100644
--- a/plat/arm/css/sgm/sgm_bl31_setup.c
+++ b/plat/arm/css/sgm/sgm_bl31_setup.c
@@ -47,3 +47,8 @@
arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
index d42afe0..125d665 100644
--- a/plat/hisilicon/hikey/hikey_bl2_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -336,7 +336,6 @@
params.flags = MMC_FLAG_CMD23;
info.mmc_dev_type = MMC_IS_EMMC;
dw_mmc_init(¶ms, &info);
- mdelay(20);
hikey_io_setup();
}
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index c1be1f6..2261470 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -14,6 +14,7 @@
#include <generic_delay_timer.h>
#include <gicv2.h>
#include <hi3660.h>
+#include <mmio.h>
#include <hisi_ipc.h>
#include <interrupt_mgmt.h>
#include <interrupt_props.h>
@@ -143,6 +144,19 @@
BL31_COHERENT_RAM_LIMIT);
}
+static void hikey960_edma_init(void)
+{
+ int i;
+ uint32_t non_secure;
+
+ non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC;
+ mmio_write_32(EDMAC_SEC_CTRL, non_secure);
+
+ for (i = 0; i < EDMAC_CHANNEL_NUMS; i++) {
+ mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18));
+ }
+}
+
void bl31_platform_setup(void)
{
/* Initialize the GIC driver, cpu and distributor interfaces */
@@ -151,6 +165,8 @@
gicv2_pcpu_distif_init();
gicv2_cpuif_enable();
+ hikey960_edma_init();
+
hisi_ipc_init();
}
diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h
index 8ce531e..c9ecd32 100644
--- a/plat/hisilicon/hikey960/include/hi3660.h
+++ b/plat/hisilicon/hikey960/include/hi3660.h
@@ -366,4 +366,11 @@
/* GPIO219: PD interrupt. pull up */
#define IOCG_AO_043_REG (IOCG_AO_REG_BASE + 0x030)
+#define EDMAC_BASE 0xfdf30000
+#define EDMAC_SEC_CTRL (EDMAC_BASE + 0x694)
+#define EDMAC_AXI_CONF(x) (EDMAC_BASE + 0x820 + (x << 6))
+#define EDMAC_SEC_CTRL_INTR_SEC (1 << 1)
+#define EDMAC_SEC_CTRL_GLOBAL_SEC (1 << 0)
+#define EDMAC_CHANNEL_NUMS 16
+
#endif /* HI3660_H */
diff --git a/plat/imx/common/imx_uart_console.S b/plat/imx/common/imx_uart_console.S
new file mode 100644
index 0000000..7dbde79
--- /dev/null
+++ b/plat/imx/common/imx_uart_console.S
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
+#include <console_macros.S>
+#include <assert_macros.S>
+#include "imx_uart.h"
+
+#define URXD 0x0 /* Receiver Register */
+#define UTXD 0x40 /* Transmitter Register */
+#define UTS 0xb4 /* UART Test Register (mx31) */
+#define URXD_RX_DATA (0xFF)
+
+ .globl console_uart_register
+ .globl console_uart_init
+ .globl console_uart_putc
+ .globl console_uart_getc
+
+func console_imx_uart_register
+ mov x7, x30
+ mov x6, x3
+ cbz x6, register_fail
+ str x0, [x6, #CONSOLE_T_DRVDATA]
+
+ bl console_imx_uart_init
+ cbz x0, register_fail
+
+ mov x0, x6
+ mov x30, x7
+ finish_console_register imx_uart putc=1, getc=1
+
+register_fail:
+ ret x7
+endfunc console_imx_uart_register
+
+func console_imx_uart_init
+ mov w0, #1
+ ret
+endfunc console_imx_uart_init
+
+func console_imx_uart_putc
+ ldr x1, [x1, #CONSOLE_T_DRVDATA]
+ cbz x1, putc_error
+
+ /* Prepare '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne 2f
+1:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #UTS]
+ tbz w2, #6, 1b
+ mov w2, #0xD
+ str w2, [x1, #UTXD]
+2:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #UTS]
+ tbz w2, #6, 2b
+ str w0, [x1, #UTXD]
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+endfunc console_imx_uart_putc
+
+func console_imx_uart_getc
+ ldr x0, [x0, #CONSOLE_T_DRVDATA]
+ cbz x0, getc_error
+1:
+ ldr w1, [x0, #UTS]
+ tbnz w1, #5, 1b
+
+ ldr w1, [x0, #URXD]
+ and w0, w1, #URXD_RX_DATA
+
+ ret
+getc_error:
+ mov w0, #-1
+ ret
+endfunc console_imx_uart_getc
diff --git a/plat/imx/common/include/imx_uart.h b/plat/imx/common/include/imx_uart.h
new file mode 100644
index 0000000..d2c3968
--- /dev/null
+++ b/plat/imx/common/include/imx_uart.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_UART_H
+#define IMX_UART_H
+
+#include <console.h>
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ console_t console;
+ uintptr_t base;
+} console_uart_t;
+
+int console_uart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+ console_uart_t *console);
+#endif /*__ASSEMBLY__*/
+
+#endif /* IMX_UART_H */
diff --git a/plat/imx/imx8m/imx8mq/gpc.c b/plat/imx/imx8m/imx8mq/gpc.c
new file mode 100644
index 0000000..187a4ad
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/gpc.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <gpc.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <std_svc.h>
+
+void imx_set_cpu_secure_entry(unsigned int core_id, uintptr_t sec_entrypoint)
+{
+ uint64_t temp_base;
+
+ temp_base = (uint64_t) sec_entrypoint;
+ temp_base >>= 2;
+
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3),
+ ((uint32_t)(temp_base >> 22) & 0xffff));
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4,
+ ((uint32_t)temp_base & 0x003fffff));
+}
+
+/* use wfi power down the core */
+void imx_set_cpu_pwr_off(unsigned int core_id)
+{
+ /* enable the wfi power down of the core */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ (1 << (core_id + 20)));
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+};
+
+/* use the sw method to power up the core */
+void imx_set_cpu_pwr_on(unsigned int core_id)
+{
+ /* clear the wfi power down bit of the core */
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id));
+ /* assert the ncpuporeset */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ /* sw power up the core */
+ mmio_setbits_32(IMX_GPC_BASE + CPU_PGC_UP_TRG, (1 << core_id));
+
+ /* wait for the power up finished */
+ while ((mmio_read_32(IMX_GPC_BASE + CPU_PGC_UP_TRG) & (1 << core_id)) != 0)
+ ;
+
+ /* deassert the pcg pcr bit of the core */
+ mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ /* deassert the ncpuporeset */
+ mmio_setbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+}
+
+/* if out of lpm, we need to do reverse steps */
+void imx_set_cpu_lpm(unsigned int core_id, bool pdn)
+{
+ if (pdn) {
+ /* enable the core WFI PDN & IRQ PUP */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ (1 << (core_id + 20)) | COREx_IRQ_WUP(core_id));
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ } else {
+ /* disable CORE WFI PDN & IRQ PUP */
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ COREx_IRQ_WUP(core_id));
+ /* deassert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ }
+}
+
+void imx_set_sys_wakeup(unsigned int last_core, bool pdn)
+{
+ /* TODO */
+}
+
+void imx_pup_pdn_slot_config(int last_core, bool pdn)
+{
+ if (pdn) {
+ /* SLOT0 for A53 PLAT power down */
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), SLT_PLAT_PDN);
+ /* SLOT1 for A53 PLAT power up */
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(1), SLT_PLAT_PUP);
+ /* SLOT2 for A53 primary core power up */
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(2), SLT_COREx_PUP(last_core));
+ /* ACK setting: PLAT ACK for PDN, CORE ACK for PUP */
+ mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF,
+ A53_PLAT_PDN_ACK | A53_PLAT_PUP_ACK);
+ } else {
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), 0xFFFFFFFF);
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(1), 0xFFFFFFFF);
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(2), 0xFFFFFFFF);
+ mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF,
+ A53_DUMMY_PDN_ACK | A53_DUMMY_PUP_ACK);
+ }
+}
+
+void imx_set_cluster_standby(bool retention)
+{
+ /*
+ * Enable BIT 6 of A53 AD register to make sure system
+ * don't enter LPM mode.
+ */
+ if (retention)
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+ else
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+}
+
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state)
+{
+ uint32_t val;
+
+ if (is_local_state_off(power_state)) {
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val |= A53_LPM_STOP; /* enable C0-C1's STOP mode */
+ val &= ~CPU_CLOCK_ON_LPM; /* disable CPU clock in LPM mode */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* enable C2-3's STOP mode */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_STOP);
+
+ /* enable PLAT/SCU power down */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+ val &= ~EN_L2_WFI_PDN;
+ val |= L2PGE | EN_PLAT_PDN;
+ val &= ~COREx_IRQ_WUP(last_core); /* disable IRQ PUP for last core */
+ val |= COREx_LPM_PUP(last_core); /* enable LPM PUP for last core */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+
+ imx_pup_pdn_slot_config(last_core, true);
+
+ /* enable PLAT PGC */
+ mmio_setbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1);
+ } else {
+ /* clear PLAT PGC */
+ mmio_clrbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1);
+
+ /* clear the slot and ack for cluster power down */
+ imx_pup_pdn_slot_config(last_core, false);
+
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val &= ~A53_LPM_MASK; /* clear the C0~1 LPM */
+ val |= CPU_CLOCK_ON_LPM; /* disable cpu clock in LPM */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* set A53 LPM to RUN mode */
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_MASK);
+
+ /* clear PLAT/SCU power down */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+ val |= EN_L2_WFI_PDN;
+ val &= ~(L2PGE | EN_PLAT_PDN);
+ val &= ~COREx_LPM_PUP(last_core); /* disable C0's LPM PUP */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+ }
+}
+
+/* config the system level power mode */
+void imx_set_sys_lpm(bool retention)
+{
+ uint32_t val;
+
+ /* set system DSM mode SLPCR(0x14) */
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+ SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN);
+
+ if (retention)
+ val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+ SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN |
+ SLPCR_A53_FASTWUP_STOP_MODE);
+
+ mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+}
+
+void imx_set_rbc_count(void)
+{
+ mmio_setbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT);
+}
+
+void imx_clear_rbc_count(void)
+{
+ mmio_clrbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT);
+}
+
+void imx_gpc_init(void)
+{
+ uint32_t val;
+ int i;
+ /* mask all the interrupt by default */
+ /* Due to the hardware design requirement, need to make
+ * sure GPR interrupt(#32) is unmasked during RUN mode to
+ * avoid entering DSM mode by mistake.
+ */
+ for (i = 0; i < 4; i++) {
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, 0xFFFFFFFE);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, 0xFFFFFFFE);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, 0xFFFFFFFE);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, 0xFFFFFFFE);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+ }
+
+ /* use external IRQs to wakeup C0~C3 from LPM */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val |= IRQ_SRC_A53_WUP;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~MASTER0_LPM_HSK;
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* mask M4 DSM trigger if M4 is NOT enabled */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_M4, DSM_MODE_MASK);
+
+ /* set all mix/PU in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xfffd);
+
+ /* set SCU timming */
+ mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+ (0x59 << 10) | 0x5B | (0x2 << 20));
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK |
+ A53_DUMMY_PDN_ACK);
+
+ /* disable DSM mode by default */
+ mmio_clrbits_32(IMX_GPC_BASE + SLPCR, DSM_MODE_MASK);
+
+ /*
+ * USB PHY power up needs to make sure RESET bit in SRC is clear,
+ * otherwise, the PU power up bit in GPC will NOT self-cleared.
+ * only need to do it once.
+ */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+}
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
new file mode 100644
index 0000000..45d2a40
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <gpc.h>
+#include <imx_uart.h>
+#include <stdbool.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+#include <xlat_tables.h>
+#include <tzc380.h>
+
+IMPORT_SYM(uintptr_t, __COHERENT_RAM_START__, BL31_COHERENT_RAM_START);
+IMPORT_SYM(uintptr_t, __COHERENT_RAM_END__, BL31_COHERENT_RAM_END);
+IMPORT_SYM(uintptr_t, __RO_START__, BL31_RO_START);
+IMPORT_SYM(uintptr_t, __RO_END__, BL31_RO_END);
+IMPORT_SYM(uintptr_t, __RW_START__, BL31_RW_START);
+IMPORT_SYM(uintptr_t, __RW_END__, BL31_RW_END);
+
+static const mmap_region_t imx_mmap[] = {
+ MAP_REGION_FLAT(GPV_BASE, GPV_SIZE, MT_DEVICE | MT_RW), /* GPV map */
+ MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
+ MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), /* GIC map */
+ {0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+static void bl31_tz380_setup(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + IOMUXC_GPR10);
+ if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+ return;
+
+ tzc380_init(IMX_TZASC_BASE);
+ /*
+ * Need to substact offset 0x40000000 from CPU address when
+ * programming tzasc region for i.mx8mq. Enable 1G-5G S/NS RW
+ */
+ tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+ TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ int i;
+ /* enable CSU NS access permission */
+ for (i = 0; i < 64; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, 0xffffffff);
+ }
+
+#if DEBUG_CONSOLE
+ static console_uart_t console;
+
+ console_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+#endif
+ /*
+ * tell BL3-1 where the non-secure software image is located
+ * and the entry state information.
+ */
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ bl31_tz380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+ mmap_add_region(BL31_RO_START, BL31_RO_START, (BL31_RO_END - BL31_RO_START),
+ MT_MEMORY | MT_RO | MT_SECURE);
+ mmap_add_region(BL31_RW_START, BL31_RW_START, (BL31_RW_END - BL31_RW_START),
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ mmap_add(imx_mmap);
+
+#if USE_COHERENT_MEM
+ mmap_add_region(BL31_COHERENT_RAM_START, BL31_COHERENT_RAM_START,
+ BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+ /* setup xlat table */
+ init_xlat_tables();
+ /* enable the MMU */
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ /* init the GICv3 cpu and distributor interface */
+ plat_gic_driver_init();
+ plat_gic_init();
+
+ /* gpc init */
+ imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ if (type == SECURE)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ return;
+}
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
new file mode 100644
index 0000000..7afe52d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <gpc.h>
+#include <stdbool.h>
+#include <plat_imx8.h>
+#include <psci.h>
+#include <mmio.h>
+
+#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core_id;
+ uint64_t base_addr = BL31_BASE;
+
+ core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* set the secure entrypoint */
+ imx_set_cpu_secure_entry(core_id, base_addr);
+ /* power up the core */
+ imx_set_cpu_pwr_on(core_id);
+
+ return PSCI_E_SUCCESS;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* program the GIC per cpu dist and rdist interface */
+ plat_gic_pcpu_init();
+ /* enable the GICv3 cpu interface */
+ plat_gic_cpuif_enable();
+}
+
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* disable the GIC cpu interface first */
+ plat_gic_cpuif_disable();
+ /* config the core for power down */
+ imx_set_cpu_pwr_off(core_id);
+}
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+ /* The non-secure entrypoint should be in RAM space */
+ if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET)
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int pwr_type = psci_get_pstate_type(power_state);
+ int state_id = psci_get_pstate_id(power_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ if (pwr_type == PSTATE_TYPE_STANDBY) {
+ CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ }
+
+ if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) {
+ CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE;
+ CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+void imx_cpu_standby(plat_local_state_t cpu_state)
+{
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+
+ wfi();
+
+ write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+ isb();
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint64_t base_addr = BL31_BASE;
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ /* disable the cpu interface */
+ plat_gic_cpuif_disable();
+ imx_set_cpu_secure_entry(core_id, base_addr);
+ imx_set_cpu_lpm(core_id, true);
+ } else {
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+ }
+
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+ imx_set_cluster_powerdown(core_id, true);
+ else
+ imx_set_cluster_standby(true);
+
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ imx_set_sys_lpm(true);
+ }
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* check the system level status */
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ imx_set_sys_lpm(false);
+ imx_clear_rbc_count();
+ }
+
+ /* check the cluster level power status */
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+ imx_set_cluster_powerdown(core_id, false);
+ else
+ imx_set_cluster_standby(false);
+
+ /* check the core level power status */
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ /* clear the core lpm setting */
+ imx_set_cpu_lpm(core_id, false);
+ /* enable the gic cpu interface */
+ plat_gic_cpuif_enable();
+ } else {
+ write_scr_el3(read_scr_el3() & (~0x4));
+ isb();
+ }
+}
+
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ for (i = IMX_PWR_LVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE;
+
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE;
+}
+
+void __dead2 imx_system_reset(void)
+{
+ uintptr_t wdog_base = IMX_WDOG_BASE;
+ unsigned int val;
+
+ /* WDOG_B reset */
+ val = mmio_read_16(wdog_base);
+#ifdef IMX_WDOG_B_RESET
+ val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_WDE |
+ WDOG_WCR_WDT | WDOG_WCR_SRS;
+#else
+ val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_SRS;
+#endif
+ mmio_write_16(wdog_base, val);
+
+ mmio_write_16(wdog_base + WDOG_WSR, 0x5555);
+ mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa);
+ while (1)
+ ;
+}
+
+
+
+void __dead2 imx_system_off(void)
+{
+ mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, SNVS_LPCR_SRTC_ENV |
+ SNVS_LPCR_DP_EN | SNVS_LPCR_TOP);
+
+ while (1)
+ ;
+}
+
+void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+ imx_set_rbc_count();
+
+ while (1)
+ wfi();
+}
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .validate_power_state = imx_validate_power_state,
+ .cpu_standby = imx_cpu_standby,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .system_reset = imx_system_reset,
+ .system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ imx_mailbox_init(sec_entrypoint);
+ /* sec_entrypoint is used for warm reset */
+ *psci_ops = &imx_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/imx/imx8m/imx8mq/include/platform_def.h b/plat/imx/imx8m/imx8mq/include/platform_def.h
new file mode 100644
index 0000000..4957582
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/platform_def.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0x800
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU 0x0
+#define PLATFORM_MAX_CPU_PER_CLUSTER 4
+#define PLATFORM_CLUSTER_COUNT 1
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 0
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(4)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define PLAT_WAIT_OFF_STATE U(2)
+#define PLAT_STOP_OFF_STATE U(3)
+
+#define BL31_BASE U(0x910000)
+#define BL31_LIMIT U(0x920000)
+#define BL32_BASE U(0xfe000000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE U(0x38800000)
+#define PLAT_GICR_BASE U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+
+#define MAX_XLAT_TABLES 4
+#define MAX_MMAP_REGIONS 14
+
+#define HAB_RVT_BASE U(0x00000880) /* HAB_RVT for i.MX8MQ */
+
+#define IMX_BOOT_UART_BASE U(0x30860000)
+#define IMX_BOOT_UART_CLK_IN_HZ 25000000 /* Select 25Mhz oscillator */
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ 25000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define IMX_AIPS_BASE U(0x30200000)
+#define IMX_AIPS_SIZE U(0xC00000)
+#define IMX_AIPS1_BASE U(0x30200000)
+#define IMX_AIPS3_ARB_BASE U(0x30800000)
+#define IMX_ANAMIX_BASE U(0x30360000)
+#define IMX_CCM_BASE U(0x30380000)
+#define IMX_SRC_BASE U(0x30390000)
+#define IMX_GPC_BASE U(0x303a0000)
+#define IMX_RDC_BASE U(0x303d0000)
+#define IMX_CSU_BASE U(0x303e0000)
+#define IMX_WDOG_BASE U(0x30280000)
+#define IMX_SNVS_BASE U(0x30370000)
+#define IMX_NOC_BASE U(0x32700000)
+#define IMX_TZASC_BASE U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE U(0x30340000)
+#define IMX_DDRC_BASE U(0x3d400000)
+#define IMX_DDRPHY_BASE U(0x3c000000)
+#define IMX_DDR_IPS_BASE U(0x3d000000)
+#define IMX_ROM_BASE U(0x00000000)
+
+#define AIPSTZ1_BASE U(0x301f0000)
+#define AIPSTZ2_BASE U(0x305f0000)
+#define AIPSTZ3_BASE U(0x309f0000)
+#define AIPSTZ4_BASE U(0x32df0000)
+
+#define GPV_BASE U(0x32000000)
+#define GPV_SIZE U(0x800000)
+#define IMX_GIC_BASE PLAT_GICD_BASE
+#define IMX_GIC_SIZE U(0x200000)
+
+#define WDOG_WSR U(0x2)
+#define WDOG_WCR_WDZST BIT(0)
+#define WDOG_WCR_WDBG BIT(1)
+#define WDOG_WCR_WDE BIT(2)
+#define WDOG_WCR_WDT BIT(3)
+#define WDOG_WCR_SRS BIT(4)
+#define WDOG_WCR_WDA BIT(5)
+#define WDOG_WCR_SRE BIT(6)
+#define WDOG_WCR_WDW BIT(7)
+
+#define SRC_A53RCR0 U(0x4)
+#define SRC_A53RCR1 U(0x8)
+#define SRC_OTG1PHY_SCR U(0x20)
+#define SRC_OTG2PHY_SCR U(0x24)
+#define SRC_GPR1_OFFSET U(0x74)
+
+#define SNVS_LPCR U(0x38)
+#define SNVS_LPCR_SRTC_ENV BIT(0)
+#define SNVS_LPCR_DP_EN BIT(5)
+#define SNVS_LPCR_TOP BIT(6)
+
+
+#define IOMUXC_GPR10 U(0x28)
+#define GPR_TZASC_EN BIT(0)
+#define GPR_TZASC_EN_LOCK BIT(16)
+
+#define OCRAM_S_BASE U(0x00180000)
+#define OCRAM_S_SIZE U(0x8000)
+#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
+
+#define COUNTER_FREQUENCY 8000000 /* 8MHz */
+
+#define DEBUG_CONSOLE 0
+#define IMX_WDOG_B_RESET
+#define PLAT_IMX8M 1
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
new file mode 100644
index 0000000..0255268
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := -Iplat/imx/common/include \
+ -Iplat/imx/imx8m/include \
+ -Iplat/imx/imx8m/imx8mq/include
+
+IMX_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \
+ drivers/arm/gic/v3/arm_gicv3_common.c \
+ drivers/arm/gic/v3/gic500.c \
+ drivers/arm/gic/v3/gicv3_main.c \
+ drivers/arm/gic/common/gic_common.c \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c \
+ plat/imx/imx8m/imx8mq/imx8mq_psci.c \
+ plat/imx/imx8m/imx8mq/gpc.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx_uart_console.S \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/console/aarch64/console.S \
+ drivers/arm/tzc/tzc380.c \
+ ${IMX_GIC_SOURCES}
+
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+MULTI_CONSOLE_API := 1
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
new file mode 100644
index 0000000..6fdf6ad
--- /dev/null
+++ b/plat/imx/imx8m/include/gpc.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8M_GPC_H
+#define IMX8M_GPC_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x108
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x40
+#define IMR1_CORE2_A53 0x1C0
+#define IMR1_CORE3_A53 0x1D0
+#define IMR1_CORE0_M4 0x50
+#define SLT0_CFG 0xB0
+#define GPC_PU_PWRHSK 0x1FC
+#define PGC_CPU_0_1_MAPPING 0xEC
+#define CPU_PGC_UP_TRG 0xF0
+#define PU_PGC_UP_TRG 0xF8
+#define CPU_PGC_DN_TRG 0xFC
+#define PU_PGC_DN_TRG 0x104
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+
+#define A53_DUMMY_PDN_ACK BIT(15)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(2)
+#define A53_PLAT_PUP_ACK BIT(18)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+/* helper macro */
+#define A53_LPM_MASK U(0xF)
+#define A53_LPM_WAIT U(0x5)
+#define A53_LPM_STOP U(0xA)
+
+#define DSM_MODE_MASK BIT(31)
+
+#define A53_CORE_WUP_SRC(core_id) (1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2))
+#define COREx_PGC_PCR(core_id) (0x800 + (core_id) * 0x40)
+#define COREx_WFI_PDN(core_id) (1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16))
+#define COREx_IRQ_WUP(core_id) ((core_id) < 2 ? (1 << ((core_id) * 2 + 8)) : (1 << ((core_id) * 2 + 20)))
+#define COREx_LPM_PUP(core_id) ((core_id) < 2 ? (1 << ((core_id) * 2 + 9)) : (1 << ((core_id) * 2 + 21)))
+#define SLTx_CFG(n) ((SLT0_CFG + ((n) * 4)))
+#define SLT_COREx_PUP(core_id) (0x2 << ((core_id) * 2))
+
+/* function declare */
+void imx_gpc_init(void);
+void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
+void imx_set_cpu_pwr_off(unsigned int core_index);
+void imx_set_cpu_pwr_on(unsigned int core_index);
+void imx_set_cpu_lpm(unsigned int core_index, bool pdn);
+void imx_set_cluster_standby(bool retention);
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state);
+void imx_set_sys_lpm(bool retention);
+void imx_set_rbc_count(void);
+void imx_clear_rbc_count(void);
+
+#endif /*IMX8M_GPC_H */
diff --git a/plat/layerscape/board/ls1043/include/soc_tzasc.h b/plat/layerscape/board/ls1043/include/soc_tzasc.h
index b2483d9..46dfba0 100644
--- a/plat/layerscape/board/ls1043/include/soc_tzasc.h
+++ b/plat/layerscape/board/ls1043/include/soc_tzasc.h
@@ -7,8 +7,6 @@
#ifndef SOC_TZASC_H
#define SOC_TZASC_H
-#include "tzc380.h"
-
#define MAX_NUM_TZC_REGION 3
/* TZASC related constants */
@@ -58,6 +56,15 @@
#define CCI_TERMINATE_BARRIER_TX 0x8
#define CONFIG_SYS_FSL_TZASC_ADDR 0x1500000
+struct tzc380_reg {
+ unsigned int secure;
+ unsigned int enabled;
+ unsigned int low_addr;
+ unsigned int high_addr;
+ unsigned int size;
+ unsigned int sub_mask;
+};
+
/* List of MAX_NUM_TZC_REGION TZC regions' boundaries and configurations. */
static const struct tzc380_reg tzc380_reg_list[] = {
diff --git a/plat/layerscape/common/include/tzc380.h b/plat/layerscape/common/include/tzc380.h
deleted file mode 100644
index 88063a9..0000000
--- a/plat/layerscape/common/include/tzc380.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef TZC380_H
-#define TZC380_H
-
-struct tzc380_reg {
- unsigned int secure;
- unsigned int enabled;
- unsigned int low_addr;
- unsigned int high_addr;
- unsigned int size;
- unsigned int sub_mask;
-};
-
-#endif /* TZC380_H */
diff --git a/plat/marvell/a3700/common/plat_pm.c b/plat/marvell/a3700/common/plat_pm.c
index 5cebc92..dce4841 100644
--- a/plat/marvell/a3700/common/plat_pm.c
+++ b/plat/marvell/a3700/common/plat_pm.c
@@ -288,18 +288,9 @@
*/
void a3700_pwr_domain_off(const psci_power_state_t *target_state)
{
- uint32_t cpu_idx = plat_my_core_pos();
-
/* Prevent interrupts from spuriously waking up this cpu */
plat_marvell_gic_cpuif_disable();
- /*
- * Enable Core VDD OFF, core is supposed to be powered
- * off by PMU when WFI command is issued.
- */
- mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG + 4 * cpu_idx,
- MVEBU_PM_CORE_PD);
-
/* Core can not be powered down with pending IRQ,
* acknowledge all the pending IRQ
*/
diff --git a/plat/marvell/a8k/a80x0/board/phy-porting-layer.h b/plat/marvell/a8k/a80x0/board/phy-porting-layer.h
index 38497fb..abd85b5 100644
--- a/plat/marvell/a8k/a80x0/board/phy-porting-layer.h
+++ b/plat/marvell/a8k/a80x0/board/phy-porting-layer.h
@@ -27,7 +27,14 @@
.g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
.valid = 0x1 }, /* Comphy2 */
{ 0 }, /* Comphy3 */
- { 0 }, /* Comphy4 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+ .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 0x1 }, /* Comphy4 */
{ 0 }, /* Comphy5 */
},
@@ -44,7 +51,14 @@
.g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
.valid = 0x1 }, /* Comphy2 */
{ 0 }, /* Comphy3 */
- { 0 }, /* Comphy4 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+ .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 0x1 }, /* Comphy4 */
{ 0 }, /* Comphy5 */
},
},
diff --git a/plat/marvell/a8k/common/a8k_common.mk b/plat/marvell/a8k/common/a8k_common.mk
index 7f01e13..e350d6a 100644
--- a/plat/marvell/a8k/common/a8k_common.mk
+++ b/plat/marvell/a8k/common/a8k_common.mk
@@ -13,6 +13,9 @@
MARVELL_DRV_BASE := drivers/marvell
MARVELL_COMMON_BASE := plat/marvell/common
+MARVELL_SVC_TEST := 0
+$(eval $(call add_define,MARVELL_SVC_TEST))
+
ERRATA_A72_859971 := 1
# Enable MSS support for a8k family
@@ -59,14 +62,15 @@
MARVELL_MOCHI_DRV += $(MARVELL_DRV_BASE)/mochi/cp110_setup.c
-BLE_SOURCES := drivers/mentor/i2c/mi2cv.c \
- $(PLAT_COMMON_BASE)/plat_ble_setup.c \
- $(MARVELL_MOCHI_DRV) \
- $(PLAT_COMMON_BASE)/plat_pm.c \
- $(MARVELL_DRV_BASE)/thermal.c \
- $(PLAT_COMMON_BASE)/plat_thermal.c \
- $(BLE_PORTING_SOURCES) \
- $(MARVELL_DRV_BASE)/ccu.c \
+BLE_SOURCES := drivers/mentor/i2c/mi2cv.c \
+ $(PLAT_COMMON_BASE)/plat_ble_setup.c \
+ $(MARVELL_MOCHI_DRV) \
+ $(PLAT_COMMON_BASE)/plat_pm.c \
+ $(MARVELL_DRV_BASE)/ap807_clocks_init.c \
+ $(MARVELL_DRV_BASE)/thermal.c \
+ $(PLAT_COMMON_BASE)/plat_thermal.c \
+ $(BLE_PORTING_SOURCES) \
+ $(MARVELL_DRV_BASE)/ccu.c \
$(MARVELL_DRV_BASE)/io_win.c
BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
diff --git a/plat/marvell/a8k/common/mss/mss_pm_ipc.c b/plat/marvell/a8k/common/mss/mss_pm_ipc.c
index 6ff4abc..d1297b0 100644
--- a/plat/marvell/a8k/common/mss/mss_pm_ipc.c
+++ b/plat/marvell/a8k/common/mss/mss_pm_ipc.c
@@ -26,7 +26,7 @@
#define MSS_MSG_INT_MASK (0x80000000)
#define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110)
-#define MSS_TRIGGER_TIMEOUT (1000)
+#define MSS_TRIGGER_TIMEOUT (2000)
/*****************************************************************************
* mss_pm_ipc_msg_send
diff --git a/plat/marvell/a8k/common/plat_ble_setup.c b/plat/marvell/a8k/common/plat_ble_setup.c
index 7438f69..dbadeb7 100644
--- a/plat/marvell/a8k/common/plat_ble_setup.c
+++ b/plat/marvell/a8k/common/plat_ble_setup.c
@@ -15,14 +15,15 @@
#include <mv_ddr_if.h>
#include <mvebu_def.h>
#include <plat_marvell.h>
+#include "ap807_clocks_init.h"
/* Register for skip image use */
#define SCRATCH_PAD_REG2 0xF06F00A8
#define SCRATCH_PAD_SKIP_VAL 0x01
#define NUM_OF_GPIO_PER_REG 32
-#define MMAP_SAVE_AND_CONFIG 0
-#define MMAP_RESTORE_SAVED 1
+#define MMAP_SAVE_AND_CONFIG 0
+#define MMAP_RESTORE_SAVED 1
/* SAR clock settings */
#define MVEBU_AP_GEN_MGMT_BASE (MVEBU_RFU_BASE + 0x8000)
@@ -40,6 +41,7 @@
#define SAR_CLOCK_FREQ_MODE(v) (((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \
SAR_CLOCK_FREQ_MODE_OFFSET)
+#define AVS_I2C_EEPROM_ADDR 0x57 /* EEPROM */
#define AVS_EN_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x130)
#define AVS_ENABLE_OFFSET (0)
#define AVS_SOFT_RESET_OFFSET (2)
@@ -71,28 +73,25 @@
(0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \
(0x1 << AVS_SOFT_RESET_OFFSET) | \
(0x1 << AVS_ENABLE_OFFSET))
-
+/* VDD limit is 0.82V for all A3900 devices
+ * AVS offsets are not the same as in A70x0
+ */
#define AVS_A3900_CLK_VALUE ((0x80 << 24) | \
(0x2c2 << 13) | \
(0x2c2 << 3) | \
(0x1 << AVS_SOFT_RESET_OFFSET) | \
(0x1 << AVS_ENABLE_OFFSET))
+/* VDD is 0.88V for 2GHz clock */
+#define AVS_A3900_HIGH_CLK_VALUE ((0x80 << 24) | \
+ (0x2f5 << 13) | \
+ (0x2f5 << 3) | \
+ (0x1 << AVS_SOFT_RESET_OFFSET) | \
+ (0x1 << AVS_ENABLE_OFFSET))
#define MVEBU_AP_EFUSE_SRV_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x8)
#define EFUSE_SRV_CTRL_LD_SELECT_OFFS 6
#define EFUSE_SRV_CTRL_LD_SEL_USER_MASK (1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS)
-/* Notify bootloader on DRAM setup */
-#define AP807_CPU_ARO_0_CTRL_0 (MVEBU_RFU_BASE + 0x82A8)
-#define AP807_CPU_ARO_1_CTRL_0 (MVEBU_RFU_BASE + 0x8D00)
-
-/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
-#define AP807_CPU_ARO_CLK_EN_OFFSET 0
-#define AP807_CPU_ARO_CLK_EN_MASK (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
-
-/* 0 - ARO is the clock source, 1 - PLL is the clock source */
-#define AP807_CPU_ARO_SEL_PLL_OFFSET 5
-#define AP807_CPU_ARO_SEL_PLL_MASK (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
/*
* - Identification information in the LD-0 eFuse:
@@ -143,9 +142,16 @@
#define EFUSE_AP_LD0_WP_MASK 0x3FF
#endif
-#define EFUSE_AP_LD0_SVC4_OFFS 42 /* LD0[112:105] */
+#define EFUSE_AP_LD0_SVC4_OFFS 42 /* LD0[112:105] */
-#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4
+#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4
+
+#if MARVELL_SVC_TEST
+#define MVEBU_CP_MPP_CTRL37_OFFS 20
+#define MVEBU_CP_MPP_CTRL38_OFFS 24
+#define MVEBU_CP_MPP_I2C_FUNC 2
+#define MVEBU_MPP_CTRL_MASK 0xf
+#endif
/* Return the AP revision of the chip */
static unsigned int ble_get_ap_type(void)
@@ -205,41 +211,156 @@
* Setup Adaptive Voltage Switching - this is required for some platforms
****************************************************************************
*/
+#if !MARVELL_SVC_TEST
static void ble_plat_avs_config(void)
{
- uint32_t reg_val, device_id;
+ uint32_t freq_mode, device_id;
+ uint32_t avs_val = 0;
+ freq_mode =
+ SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+ FREQ_MODE_AP_SAR_REG_NUM)));
/* Check which SoC is running and act accordingly */
if (ble_get_ap_type() == CHIP_ID_AP807) {
- VERBOSE("AVS: Setting AP807 AVS CTRL to 0x%x\n",
- AVS_A3900_CLK_VALUE);
- mmio_write_32(AVS_EN_CTRL_REG, AVS_A3900_CLK_VALUE);
- return;
+ /* Increase CPU voltage for higher CPU clock */
+ if (freq_mode == CPU_2000_DDR_1200_RCLK_1200)
+ avs_val = AVS_A3900_HIGH_CLK_VALUE;
+ else
+ avs_val = AVS_A3900_CLK_VALUE;
+ } else {
+ /* Check which SoC is running and act accordingly */
+ device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
+ switch (device_id) {
+ case MVEBU_80X0_DEV_ID:
+ case MVEBU_80X0_CP115_DEV_ID:
+ /* Always fix the default AVS value on A80x0 */
+ avs_val = AVS_A8K_CLK_VALUE;
+ break;
+ case MVEBU_70X0_DEV_ID:
+ case MVEBU_70X0_CP115_DEV_ID:
+ /* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */
+ if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) &&
+ (freq_mode < CPU_DDR_RCLK_INVALID))
+ avs_val = AVS_A7K_LOW_CLK_VALUE;
+ break;
+ default:
+ ERROR("Unsupported Device ID 0x%x\n", device_id);
+ return;
+ }
}
- /* Check which SoC is running and act accordingly */
- device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
- switch (device_id) {
- case MVEBU_80X0_DEV_ID:
- case MVEBU_80X0_CP115_DEV_ID:
- /* Set the new AVS value - fix the default one on A80x0 */
- mmio_write_32(AVS_EN_CTRL_REG, AVS_A8K_CLK_VALUE);
- break;
- case MVEBU_70X0_DEV_ID:
- case MVEBU_70X0_CP115_DEV_ID:
- /* Only fix AVS for CPU clocks lower than 1600MHz on A70x0 */
- reg_val = mmio_read_32(MVEBU_AP_SAR_REG_BASE(
- FREQ_MODE_AP_SAR_REG_NUM));
- reg_val &= SAR_CLOCK_FREQ_MODE_MASK;
- reg_val >>= SAR_CLOCK_FREQ_MODE_OFFSET;
- if ((reg_val > CPU_1600_DDR_900_RCLK_900_2) &&
- (reg_val < CPU_DDR_RCLK_INVALID))
- mmio_write_32(AVS_EN_CTRL_REG, AVS_A7K_LOW_CLK_VALUE);
- break;
- default:
- ERROR("Unsupported Device ID 0x%x\n", device_id);
+ if (avs_val) {
+ VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val);
+ mmio_write_32(AVS_EN_CTRL_REG, avs_val);
}
}
+#endif
+/******************************************************************************
+ * Update or override current AVS work point value using data stored in EEPROM
+ * This is only required by QA/validation flows and activated by
+ * MARVELL_SVC_TEST flag.
+ *
+ * The function is expected to be called twice.
+ *
+ * First time with AVS value of 0 for testing if the EEPROM requests completely
+ * override the AVS value and bypass the eFuse test
+ *
+ * Second time - with non-zero AVS value obtained from eFuses as an input.
+ * In this case the EEPROM may contain AVS correction value (either positive
+ * or negative) that is added to the input AVS value and returned back for
+ * further processing.
+ ******************************************************************************
+ */
+static uint32_t avs_update_from_eeprom(uint32_t avs_workpoint)
+{
+ uint32_t new_wp = avs_workpoint;
+#if MARVELL_SVC_TEST
+ /* ---------------------------------------------------------------------
+ * EEPROM | Data description (avs_step)
+ * address |
+ * ---------------------------------------------------------------------
+ * 0x120 | AVS workpoint correction value
+ * | if not 0 and not 0xff, correct the AVS taken from eFuse
+ * | by the number of steps indicated by bit[6:0]
+ * | bit[7] defines correction direction.
+ * | If bit[7]=1, add the value from bit[6:0] to AVS workpoint,
+ * | othervise substruct this value from AVS workpoint.
+ * ---------------------------------------------------------------------
+ * 0x121 | AVS workpoint override value
+ * | Override the AVS workpoint with the value stored in this
+ * | byte. When running on AP806, the AVS workpoint is 7 bits
+ * | wide and override value is valid when bit[6:0] holds
+ * | value greater than zero and smaller than 0x33.
+ * | When running on AP807, the AVS workpoint is 10 bits wide.
+ * | Additional 2 MSB bits are supplied by EEPROM byte 0x122.
+ * | AVS override value is valid when byte @ 0x121 and bit[1:0]
+ * | of byte @ 0x122 combined have non-zero value.
+ * ---------------------------------------------------------------------
+ * 0x122 | Extended AVS workpoint override value
+ * | Valid only for AP807 platforms and must be less than 0x4
+ * ---------------------------------------------------------------------
+ */
+ static uint8_t avs_step[3] = {0};
+ uintptr_t reg;
+ uint32_t val;
+ unsigned int ap_type = ble_get_ap_type();
+
+ /* Always happens on second call to this function */
+ if (avs_workpoint != 0) {
+ /* Get correction steps from the EEPROM */
+ if ((avs_step[0] != 0) && (avs_step[0] != 0xff)) {
+ NOTICE("AVS request to step %s by 0x%x from old 0x%x\n",
+ avs_step[0] & 0x80 ? "DOWN" : "UP",
+ avs_step[0] & 0x7f, new_wp);
+ if (avs_step[0] & 0x80)
+ new_wp -= avs_step[0] & 0x7f;
+ else
+ new_wp += avs_step[0] & 0x7f;
+ }
+
+ return new_wp;
+ }
+
+ /* AVS values are located in EEPROM
+ * at CP0 i2c bus #0, device 0x57 offset 0x120
+ * The SDA and SCK pins of CP0 i2c-0: MPP[38:37], i2c function 0x2.
+ */
+ reg = MVEBU_CP_MPP_REGS(0, 4);
+ val = mmio_read_32(reg);
+ val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
+ val |= (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL38_OFFS);
+ mmio_write_32(reg, val);
+
+ /* Init CP0 i2c-0 */
+ i2c_init((void *)(MVEBU_CP0_I2C_BASE));
+
+ /* Read EEPROM only once at the fist call! */
+ i2c_read(AVS_I2C_EEPROM_ADDR, 0x120, 2, avs_step, 3);
+ NOTICE("== SVC test build ==\n");
+ NOTICE("EEPROM holds values 0x%x, 0x%x and 0x%x\n",
+ avs_step[0], avs_step[1], avs_step[2]);
+
+ /* Override the AVS value? */
+ if ((ap_type != CHIP_ID_AP807) && (avs_step[1] < 0x33)) {
+ /* AP806 - AVS is 7 bits */
+ new_wp = avs_step[1];
+
+ } else if (ap_type == CHIP_ID_AP807 && (avs_step[2] < 0x4)) {
+ /* AP807 - AVS is 10 bits */
+ new_wp = avs_step[2];
+ new_wp <<= 8;
+ new_wp |= avs_step[1];
+ }
+
+ if (new_wp == 0)
+ NOTICE("Ignore BAD AVS Override value in EEPROM!\n");
+ else
+ NOTICE("Override AVS by EEPROM value 0x%x\n", new_wp);
+#endif /* MARVELL_SVC_TEST */
+ return new_wp;
+}
/****************************************************************************
* SVC flow - v0.10
@@ -262,6 +383,11 @@
unsigned int ap_type;
/* Set access to LD0 */
+ avs_workpoint = avs_update_from_eeprom(0);
+ if (avs_workpoint)
+ goto set_aws_wp;
+
+ /* Set access to LD0 */
reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG);
reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_OFFS;
mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val);
@@ -279,7 +405,12 @@
sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK;
if (sw_ver < 1) {
NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver);
+#if MARVELL_SVC_TEST
+ NOTICE("SVC_TEST: AVS bypassed\n");
+
+#else
ble_plat_avs_config();
+#endif
return;
}
@@ -447,6 +578,10 @@
if (ap_type != CHIP_ID_AP807)
avs_workpoint &= 0x7F;
+ /* Update WP from EEPROM if needed */
+ avs_workpoint = avs_update_from_eeprom(avs_workpoint);
+
+set_aws_wp:
reg_val = mmio_read_32(AVS_EN_CTRL_REG);
NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n",
(reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET,
@@ -543,35 +678,11 @@
}
#endif
-/* Switch to ARO from PLL in ap807 */
-static void aro_to_pll(void)
-{
- unsigned int reg;
-
- /* switch from ARO to PLL */
- reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
- reg |= AP807_CPU_ARO_SEL_PLL_MASK;
- mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
- reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
- reg |= AP807_CPU_ARO_SEL_PLL_MASK;
- mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-
- mdelay(1000);
-
- /* disable ARO clk driver */
- reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
- reg |= (AP807_CPU_ARO_CLK_EN_MASK);
- mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
- reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
- reg |= (AP807_CPU_ARO_CLK_EN_MASK);
- mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-}
int ble_plat_setup(int *skip)
{
int ret;
+ unsigned int freq_mode;
/* Power down unused CPUs */
plat_marvell_early_cpu_powerdown();
@@ -598,9 +709,14 @@
/* Setup AVS */
ble_plat_svc_config();
+ /* read clk option from sampled-at-reset register */
+ freq_mode =
+ SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+ FREQ_MODE_AP_SAR_REG_NUM)));
+
/* work with PLL clock driver in AP807 */
if (ble_get_ap_type() == CHIP_ID_AP807)
- aro_to_pll();
+ ap807_clocks_init(freq_mode);
/* Do required AP setups for BLE stage */
ap_ble_init();
diff --git a/plat/marvell/a8k/common/plat_pm.c b/plat/marvell/a8k/common/plat_pm.c
index 1b68d07..2854416 100644
--- a/plat/marvell/a8k/common/plat_pm.c
+++ b/plat/marvell/a8k/common/plat_pm.c
@@ -79,7 +79,7 @@
#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 1
#define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 0
#else
-#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0
+ #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0
#define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 31
#endif
@@ -106,7 +106,7 @@
#define AP807_PWRC_LDO_CR0_OFFSET 16
#define AP807_PWRC_LDO_CR0_MASK \
(0xff << AP807_PWRC_LDO_CR0_OFFSET)
-#define AP807_PWRC_LDO_CR0_VAL 0xfd
+#define AP807_PWRC_LDO_CR0_VAL 0xfc
/*
* Power down CPU:
diff --git a/plat/marvell/common/mrvl_sip_svc.c b/plat/marvell/common/mrvl_sip_svc.c
index 8bc633b..bc4b621 100644
--- a/plat/marvell/common/mrvl_sip_svc.c
+++ b/plat/marvell/common/mrvl_sip_svc.c
@@ -87,7 +87,7 @@
SMC_RET1(handle, ret);
case MV_SIP_COMPHY_POWER_OFF:
/* x1: comphy_base, x2: comphy_index */
- ret = mvebu_cp110_comphy_power_off(x1, x2);
+ ret = mvebu_cp110_comphy_power_off(x1, x2, x3);
SMC_RET1(handle, ret);
case MV_SIP_COMPHY_PLL_LOCK:
/* x1: comphy_base, x2: comphy_index */
diff --git a/plat/marvell/version.mk b/plat/marvell/version.mk
index 16b0a16..e072e12 100644
--- a/plat/marvell/version.mk
+++ b/plat/marvell/version.mk
@@ -1 +1 @@
-SUBVERSION = devel-18.09.1
+SUBVERSION = devel-18.12.0
diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c
index fdbd4bf..b1125d1 100644
--- a/plat/st/stm32mp1/bl2_io_storage.c
+++ b/plat/st/stm32mp1/bl2_io_storage.c
@@ -282,7 +282,11 @@
}
params.device_info = &device_info;
- stm32_sdmmc2_mmc_init(¶ms);
+ if (stm32_sdmmc2_mmc_init(¶ms) != 0) {
+ ERROR("SDMMC%u init failed\n",
+ boot_context->boot_interface_instance);
+ panic();
+ }
/* Open MMC as a block device to read GPT table */
io_result = register_io_dev_block(&mmc_dev_con);