plat: marvell: Add support for Armada-37xx SoC platform
authorKonstantin Porotchkin <kostap@marvell.com>
Mon, 8 Oct 2018 13:53:09 +0000 (16:53 +0300)
committerKonstantin Porotchkin <kostap@marvell.com>
Wed, 31 Oct 2018 16:01:09 +0000 (18:01 +0200)
Add supprot for Marvell platforms based on Armada-37xx SoC.
This includes support for the official Armada-3720 modular
development board and EspressoBin community board.
The Armada-37xx SoC contains dual Cortex-A53 Application CPU,
single secure CPU (Cortex-M3) and the following interfaces:
- SATA 3.0
- USB 3.0 and USB 2.0
- PCIe
- SDIO (supports boot from eMMC)
- SPI
- UART
- I2c
- Gigabit Ethernet

Signed-off-by: Konstantin Porotchkin <kostap@marvell.com>
27 files changed:
include/plat/marvell/a3700/common/armada_common.h [new file with mode: 0644]
include/plat/marvell/a3700/common/board_marvell_def.h [new file with mode: 0644]
include/plat/marvell/a3700/common/marvell_def.h [new file with mode: 0644]
include/plat/marvell/a3700/common/plat_marvell.h [new file with mode: 0644]
include/plat/marvell/common/aarch64/marvell_macros.S
include/plat/marvell/common/mvebu.h
plat/marvell/a3700/a3700/board/pm_src.c [new file with mode: 0644]
plat/marvell/a3700/a3700/mvebu_def.h [new file with mode: 0644]
plat/marvell/a3700/a3700/plat_bl31_setup.c [new file with mode: 0644]
plat/marvell/a3700/a3700/platform.mk [new file with mode: 0644]
plat/marvell/a3700/common/a3700_common.mk [new file with mode: 0644]
plat/marvell/a3700/common/a3700_sip_svc.c [new file with mode: 0644]
plat/marvell/a3700/common/aarch64/a3700_common.c [new file with mode: 0644]
plat/marvell/a3700/common/aarch64/plat_helpers.S [new file with mode: 0644]
plat/marvell/a3700/common/dram_win.c [new file with mode: 0644]
plat/marvell/a3700/common/include/a3700_plat_def.h [new file with mode: 0644]
plat/marvell/a3700/common/include/a3700_pm.h [new file with mode: 0644]
plat/marvell/a3700/common/include/ddr_info.h [new file with mode: 0644]
plat/marvell/a3700/common/include/dram_win.h [new file with mode: 0644]
plat/marvell/a3700/common/include/io_addr_dec.h [new file with mode: 0644]
plat/marvell/a3700/common/include/plat_macros.S [new file with mode: 0644]
plat/marvell/a3700/common/include/platform_def.h [new file with mode: 0644]
plat/marvell/a3700/common/io_addr_dec.c [new file with mode: 0644]
plat/marvell/a3700/common/marvell_plat_config.c [new file with mode: 0644]
plat/marvell/a3700/common/plat_pm.c [new file with mode: 0644]
plat/marvell/common/marvell_gicv3.c [new file with mode: 0644]
plat/marvell/marvell.mk

diff --git a/include/plat/marvell/a3700/common/armada_common.h b/include/plat/marvell/a3700/common/armada_common.h
new file mode 100644 (file)
index 0000000..9fc4634
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __ARMADA_COMMON_H__
+#define __ARMADA_COMMON_H__
+
+#include <io_addr_dec.h>
+#include <stdint.h>
+
+int marvell_get_io_dec_win_conf(struct dec_win_config **win, uint32_t *size);
+
+#endif /* __ARMADA_COMMON_H__ */
diff --git a/include/plat/marvell/a3700/common/board_marvell_def.h b/include/plat/marvell/a3700/common/board_marvell_def.h
new file mode 100644 (file)
index 0000000..49a1a5c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __BOARD_MARVELL_DEF_H__
+#define __BOARD_MARVELL_DEF_H__
+
+/*
+ * Required platform porting definitions common to all ARM
+ * development platforms
+ */
+
+/* Size of cacheable stacks */
+#if IMAGE_BL1
+#if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+#else
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+#elif IMAGE_BL2
+# if TRUSTED_BOARD_BOOT
+#  define PLATFORM_STACK_SIZE 0x1000
+# else
+#  define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif IMAGE_BL31
+# define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL32
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+
+/*
+ * PLAT_MARVELL_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if IMAGE_BLE
+#  define PLAT_MARVELL_MMAP_ENTRIES    3
+#endif
+#if IMAGE_BL1
+#  if TRUSTED_BOARD_BOOT
+#   define PLAT_MARVELL_MMAP_ENTRIES   7
+#  else
+#   define PLAT_MARVELL_MMAP_ENTRIES   6
+#  endif       /* TRUSTED_BOARD_BOOT */
+#endif
+#if IMAGE_BL2
+#  define PLAT_MARVELL_MMAP_ENTRIES    8
+#endif
+#if IMAGE_BL31
+#define PLAT_MARVELL_MMAP_ENTRIES      5
+#endif
+
+/*
+ * Platform specific page table and MMU setup constants
+ */
+#if IMAGE_BL1
+#define MAX_XLAT_TABLES                        4
+#elif IMAGE_BLE
+#  define MAX_XLAT_TABLES              4
+#elif IMAGE_BL2
+#  define MAX_XLAT_TABLES              4
+#elif IMAGE_BL31
+# define MAX_XLAT_TABLES               4
+#elif IMAGE_BL32
+#  define MAX_XLAT_TABLES              4
+#endif
+
+#define MAX_IO_DEVICES                 3
+#define MAX_IO_HANDLES                 4
+
+#define PLAT_MARVELL_TRUSTED_SRAM_SIZE 0x80000 /* 512 KB */
+
+
+#endif /* __BOARD_MARVELL_DEF_H__ */
diff --git a/include/plat/marvell/a3700/common/marvell_def.h b/include/plat/marvell/a3700/common/marvell_def.h
new file mode 100644 (file)
index 0000000..6c3a524
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __MARVELL_DEF_H__
+#define __MARVELL_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <platform_def.h>
+#include <tbbr_img_def.h>
+#include <xlat_tables.h>
+
+
+/****************************************************************************
+ * Definitions common to all MARVELL standard platforms
+ ****************************************************************************
+ */
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define MARVELL_BL31_PLAT_PARAM_VAL            0x0f1e2d3c4b5a6978ULL
+
+#define PLAT_MARVELL_NORTHB_COUNT              1
+
+#define PLAT_MARVELL_CLUSTER_COUNT             1
+
+#define MARVELL_CACHE_WRITEBACK_SHIFT          6
+
+/*
+ * Macros mapping the MPIDR Affinity levels to MARVELL Platform Power levels.
+ * The power levels have a 1:1 mapping with the MPIDR affinity levels.
+ */
+#define MARVELL_PWR_LVL0               MPIDR_AFFLVL0
+#define MARVELL_PWR_LVL1               MPIDR_AFFLVL1
+#define MARVELL_PWR_LVL2               MPIDR_AFFLVL2
+
+/*
+ *  Macros for local power states in Marvell platforms encoded by State-ID field
+ *  within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define MARVELL_LOCAL_STATE_RUN        0
+/* Local power state for retention. Valid only for CPU power domains */
+#define MARVELL_LOCAL_STATE_RET        1
+/* Local power state for OFF/power-down.
+ * Valid for CPU and cluster power domains
+ */
+#define MARVELL_LOCAL_STATE_OFF        2
+
+/* The first 4KB of Trusted SRAM are used as shared memory */
+#define MARVELL_TRUSTED_SRAM_BASE      PLAT_MARVELL_ATF_BASE
+#define MARVELL_SHARED_RAM_BASE                MARVELL_TRUSTED_SRAM_BASE
+#define MARVELL_SHARED_RAM_SIZE                0x00001000      /* 4 KB */
+
+/* The remaining Trusted SRAM is used to load the BL images */
+#define MARVELL_BL_RAM_BASE            (MARVELL_SHARED_RAM_BASE + \
+                                        MARVELL_SHARED_RAM_SIZE)
+#define MARVELL_BL_RAM_SIZE            (PLAT_MARVELL_TRUSTED_SRAM_SIZE - \
+                                        MARVELL_SHARED_RAM_SIZE)
+
+#define MARVELL_DRAM_BASE              ULL(0x0)
+#define MARVELL_DRAM_SIZE              ULL(0x20000000)
+#define MARVELL_DRAM_END               (MARVELL_DRAM_BASE + \
+                                        MARVELL_DRAM_SIZE - 1)
+
+#define MARVELL_IRQ_SEC_PHY_TIMER              29
+
+#define MARVELL_IRQ_SEC_SGI_0          8
+#define MARVELL_IRQ_SEC_SGI_1          9
+#define MARVELL_IRQ_SEC_SGI_2          10
+#define MARVELL_IRQ_SEC_SGI_3          11
+#define MARVELL_IRQ_SEC_SGI_4          12
+#define MARVELL_IRQ_SEC_SGI_5          13
+#define MARVELL_IRQ_SEC_SGI_6          14
+#define MARVELL_IRQ_SEC_SGI_7          15
+
+#define MARVELL_MAP_SHARED_RAM         MAP_REGION_FLAT(                 \
+                                               MARVELL_SHARED_RAM_BASE, \
+                                               MARVELL_SHARED_RAM_SIZE, \
+                                               MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MARVELL_MAP_DRAM               MAP_REGION_FLAT(                \
+                                               MARVELL_DRAM_BASE,      \
+                                               MARVELL_DRAM_SIZE,      \
+                                               MT_MEMORY | MT_RW | MT_NS)
+
+
+/*
+ * The number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#if USE_COHERENT_MEM
+#define MARVELL_BL_REGIONS             3
+#else
+#define MARVELL_BL_REGIONS             2
+#endif
+
+#define MAX_MMAP_REGIONS               (PLAT_MARVELL_MMAP_ENTRIES + \
+                                        MARVELL_BL_REGIONS)
+
+#define MARVELL_CONSOLE_BAUDRATE       115200
+
+/****************************************************************************
+ * Required platform porting definitions common to all MARVELL std. platforms
+ ****************************************************************************
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE             MARVELL_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE             MARVELL_LOCAL_STATE_OFF
+
+
+#define PLATFORM_CORE_COUNT            PLAT_MARVELL_CLUSTER_CORE_COUNT
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE                (1 << MARVELL_CACHE_WRITEBACK_SHIFT)
+
+
+/*****************************************************************************
+ * BL1 specific defines.
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ *****************************************************************************
+ */
+#define BL1_RO_BASE            PLAT_MARVELL_TRUSTED_ROM_BASE
+#define BL1_RO_LIMIT           (PLAT_MARVELL_TRUSTED_ROM_BASE  \
+                                       + PLAT_MARVELL_TRUSTED_ROM_SIZE)
+/*
+ * Put BL1 RW at the top of the Trusted SRAM.
+ */
+#define BL1_RW_BASE            (MARVELL_BL_RAM_BASE +          \
+                                       MARVELL_BL_RAM_SIZE -   \
+                                       PLAT_MARVELL_MAX_BL1_RW_SIZE)
+#define BL1_RW_LIMIT           (MARVELL_BL_RAM_BASE + MARVELL_BL_RAM_SIZE)
+
+/*****************************************************************************
+ * BL2 specific defines.
+ *****************************************************************************
+ */
+/*
+ * Put BL2 just below BL31.
+ */
+#define BL2_BASE               (BL31_BASE - PLAT_MARVELL_MAX_BL2_SIZE)
+#define BL2_LIMIT              BL31_BASE
+
+/*****************************************************************************
+ * BL31 specific defines.
+ *****************************************************************************
+ */
+/*
+ * Put BL31 at the top of the Trusted SRAM.
+ */
+#define BL31_BASE              (MARVELL_BL_RAM_BASE + \
+                                       MARVELL_BL_RAM_SIZE - \
+                                       PLAT_MARVEL_MAX_BL31_SIZE)
+#define BL31_PROGBITS_LIMIT    BL1_RW_BASE
+#define BL31_LIMIT                     (MARVELL_BL_RAM_BASE +  \
+                                        MARVELL_BL_RAM_SIZE)
+
+
+#endif /* __MARVELL_DEF_H__ */
diff --git a/include/plat/marvell/a3700/common/plat_marvell.h b/include/plat/marvell/a3700/common/plat_marvell.h
new file mode 100644 (file)
index 0000000..f733d04
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __PLAT_MARVELL_H__
+#define __PLAT_MARVELL_H__
+
+#include <bl_common.h>
+#include <cassert.h>
+#include <cpu_data.h>
+#include <stdint.h>
+#include <xlat_tables.h>
+
+/*
+ * Extern declarations common to Marvell standard platforms
+ */
+extern const mmap_region_t plat_marvell_mmap[];
+
+#define MARVELL_CASSERT_MMAP                                           \
+       CASSERT((ARRAY_SIZE(plat_marvell_mmap) + MARVELL_BL_REGIONS)    \
+               <= MAX_MMAP_REGIONS,                                    \
+               assert_max_mmap_regions)
+
+/*
+ * Utility functions common to Marvell standard platforms
+ */
+void marvell_setup_page_tables(uintptr_t total_base,
+                              size_t total_size,
+                              uintptr_t code_start,
+                              uintptr_t code_limit,
+                              uintptr_t rodata_start,
+                              uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+                            , uintptr_t coh_start,
+                              uintptr_t coh_limit
+#endif
+);
+
+/* IO storage utility functions */
+void marvell_io_setup(void);
+
+/* Systimer utility function */
+void marvell_configure_sys_timer(void);
+
+/* Topology utility function */
+int marvell_check_mpidr(u_register_t mpidr);
+
+/* BL1 utility functions */
+void marvell_bl1_early_platform_setup(void);
+void marvell_bl1_platform_setup(void);
+void marvell_bl1_plat_arch_setup(void);
+
+/* BL2 utility functions */
+void marvell_bl2_early_platform_setup(meminfo_t *mem_layout);
+void marvell_bl2_platform_setup(void);
+void marvell_bl2_plat_arch_setup(void);
+uint32_t marvell_get_spsr_for_bl32_entry(void);
+uint32_t marvell_get_spsr_for_bl33_entry(void);
+
+/* BL31 utility functions */
+void marvell_bl31_early_platform_setup(void *from_bl2,
+                                      uintptr_t soc_fw_config,
+                                      uintptr_t hw_config,
+                                      void *plat_params_from_bl2);
+void marvell_bl31_platform_setup(void);
+void marvell_bl31_plat_runtime_setup(void);
+void marvell_bl31_plat_arch_setup(void);
+
+/* FIP TOC validity check */
+int marvell_io_is_toc_valid(void);
+
+/*
+ * PSCI functionality
+ */
+void marvell_psci_arch_init(int idx);
+void plat_marvell_system_reset(void);
+
+/*
+ * Optional functions required in Marvell standard platforms
+ */
+void plat_marvell_io_setup(void);
+int plat_marvell_get_alt_image_source(
+       unsigned int image_id,
+       uintptr_t *dev_handle,
+       uintptr_t *image_spec);
+unsigned int plat_marvell_calc_core_pos(u_register_t mpidr);
+
+void plat_marvell_interconnect_init(void);
+void plat_marvell_interconnect_enter_coherency(void);
+
+const mmap_region_t *plat_marvell_get_mmap(void);
+
+#endif /* __PLAT_MARVELL_H__ */
index 0102af042a58b3cb87be53bae6bbba529aaea922..faf10705f4518ac8de01deaa9de1dc4db70d8577 100644 (file)
@@ -45,7 +45,7 @@ spacer:
         * Clobbers: x0 - x10, sp
         * ---------------------------------------------
         */
-       .macro arm_print_gic_regs
+       .macro marvell_print_gic_regs
        /* Check for GICv3 system register access */
        mrs     x7, id_aa64pfr0_el1
        ubfx    x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
index a20e538e38916c580b709e1be737040edcc83d2b..a7d6c3fc2b20616367753954c80213f7a7709b9c 100644 (file)
@@ -32,7 +32,8 @@
 #define ROUND_UP_TO_POW_OF_2(number)   (1 << \
                                        (32 - __builtin_clz((number) - 1)))
 
-#define _1MB_                          (1024ULL*1024ULL)
-#define _1GB_                          (_1MB_*1024ULL)
+#define _1MB_                          (1024ULL * 1024ULL)
+#define _1GB_                          (_1MB_ * 1024ULL)
+#define _2GB_                          (2 * _1GB_)
 
 #endif /* MVEBU_H */
diff --git a/plat/marvell/a3700/a3700/board/pm_src.c b/plat/marvell/a3700/a3700/board/pm_src.c
new file mode 100644 (file)
index 0000000..bc48ce8
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+#include <a3700_pm.h>
+#include <plat_marvell.h>
+
+/* This struct provides the PM wake up src configuration */
+static struct pm_wake_up_src_config wake_up_src_cfg = {
+       .wake_up_src_num = 3,
+       .wake_up_src[0] = {
+               .wake_up_src_type = WAKE_UP_SRC_GPIO,
+               .wake_up_data = {
+                       .gpio_data.bank_num = 0, /* North Bridge */
+                       .gpio_data.gpio_num = 14
+               }
+       },
+       .wake_up_src[1] = {
+               .wake_up_src_type = WAKE_UP_SRC_GPIO,
+               .wake_up_data = {
+                       .gpio_data.bank_num = 1, /* South Bridge */
+                       .gpio_data.gpio_num = 2
+               }
+       },
+       .wake_up_src[2] = {
+               .wake_up_src_type = WAKE_UP_SRC_UART1,
+       }
+};
+
+struct pm_wake_up_src_config *mv_wake_up_src_config_get(void)
+{
+       return &wake_up_src_cfg;
+}
+
diff --git a/plat/marvell/a3700/a3700/mvebu_def.h b/plat/marvell/a3700/a3700/mvebu_def.h
new file mode 100644 (file)
index 0000000..c58f06b
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __MVEBU_DEF_H__
+#define __MVEBU_DEF_H__
+
+#include <a3700_plat_def.h>
+
+#endif /* __MVEBU_DEF_H__ */
diff --git a/plat/marvell/a3700/a3700/plat_bl31_setup.c b/plat/marvell/a3700/a3700/plat_bl31_setup.c
new file mode 100644 (file)
index 0000000..83db06f
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <dram_win.h>
+#include <io_addr_dec.h>
+#include <mmio.h>
+#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
+
+/* This routine does MPP initialization */
+static void marvell_bl31_mpp_init(void)
+{
+       mmio_clrbits_32(MVEBU_NB_GPIO_SEL_REG, 1 << MVEBU_GPIO_TW1_GPIO_EN_OFF);
+
+       /* Set hidden GPIO setting for SPI.
+        * In north_bridge_pin_out_en_high register 13804,
+        * bit 28 is the one which enables CS, CLK pins to be
+        * output, need to set it to 1.
+        * The initial value of this bit is 1, but in UART boot mode
+        * initialization, this bit is disabled and the SPI CS and CLK pins
+        * are used for downloading image purpose; so after downloading,
+        * we should set this bit to 1 again to enable SPI CS and CLK pins.
+        * And anyway, this bit value should be 1 in all modes,
+        * so here we does not judge boot mode and set this bit to 1 always.
+        */
+       mmio_setbits_32(MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG,
+                       1 << MVEBU_GPIO_NB_SPI_PIN_MODE_OFF);
+}
+
+/* This function overruns the same function in marvell_bl31_setup.c */
+void bl31_plat_arch_setup(void)
+{
+       struct dec_win_config *io_dec_map;
+       uint32_t dec_win_num;
+       struct dram_win_map dram_wins_map;
+
+       marvell_bl31_plat_arch_setup();
+
+       /* MPP init */
+       marvell_bl31_mpp_init();
+
+       /* initialize the timer for delay functionality */
+       plat_delay_timer_init();
+
+       /* CPU address decoder windows initialization. */
+       cpu_wins_init();
+
+       /* fetch CPU-DRAM window mapping information by reading
+        * CPU-DRAM decode windows (only the enabled ones)
+        */
+       dram_win_map_build(&dram_wins_map);
+
+       /* Get IO address decoder windows */
+       if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) {
+               printf("No IO address decoder windows configurations found!\n");
+               return;
+       }
+
+       /* IO address decoder init */
+       if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) {
+               printf("IO address decoder windows initialization failed!\n");
+               return;
+       }
+}
diff --git a/plat/marvell/a3700/a3700/platform.mk b/plat/marvell/a3700/a3700/platform.mk
new file mode 100644 (file)
index 0000000..4f7ac08
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier:     BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+include plat/marvell/a3700/common/a3700_common.mk
+
+include plat/marvell/common/marvell_common.mk
diff --git a/plat/marvell/a3700/common/a3700_common.mk b/plat/marvell/a3700/common/a3700_common.mk
new file mode 100644 (file)
index 0000000..ff96394
--- /dev/null
@@ -0,0 +1,176 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier:     BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+MARVELL_PLAT_BASE              := plat/marvell
+MARVELL_PLAT_INCLUDE_BASE      := include/plat/marvell
+PLAT_FAMILY                    := a3700
+PLAT_FAMILY_BASE               := $(MARVELL_PLAT_BASE)/$(PLAT_FAMILY)
+PLAT_INCLUDE_BASE              := $(MARVELL_PLAT_INCLUDE_BASE)/$(PLAT_FAMILY)
+PLAT_COMMON_BASE               := $(PLAT_FAMILY_BASE)/common
+MARVELL_DRV_BASE               := drivers/marvell
+MARVELL_COMMON_BASE            := $(MARVELL_PLAT_BASE)/common
+
+include $(MARVELL_PLAT_BASE)/marvell.mk
+
+#*********** A3700 *************
+DOIMAGEPATH    := $(WTP)
+DOIMAGETOOL    := $(DOIMAGEPATH)/wtptp/linux/tbb_linux
+
+ifeq ($(MARVELL_SECURE_BOOT),1)
+DOIMAGE_CFG    := $(DOIMAGEPATH)/atf-tim.txt
+IMAGESPATH     := $(DOIMAGEPATH)/tim/trusted
+
+TIMNCFG                := $(DOIMAGEPATH)/atf-timN.txt
+TIMNSIG                := $(IMAGESPATH)/timnsign.txt
+TIM2IMGARGS    := -i $(DOIMAGE_CFG) -n $(TIMNCFG)
+TIMN_IMAGE     := $$(grep "Image Filename:" -m 1 $(TIMNCFG) | cut -c 17-)
+else #MARVELL_SECURE_BOOT
+DOIMAGE_CFG    := $(DOIMAGEPATH)/atf-ntim.txt
+IMAGESPATH     := $(DOIMAGEPATH)/tim/untrusted
+TIM2IMGARGS    := -i $(DOIMAGE_CFG)
+endif #MARVELL_SECURE_BOOT
+
+TIMBUILD       := $(DOIMAGEPATH)/script/buildtim.sh
+TIM2IMG                := $(DOIMAGEPATH)/script/tim2img.pl
+
+# WTMI_IMG is used to specify the customized RTOS image running over
+# Service CPU (CM3 processor). By the default, it points to a
+# baremetal binary of fuse programming in A3700_utils.
+WTMI_IMG       := $(DOIMAGEPATH)/wtmi/fuse/build/fuse.bin
+
+# WTMI_SYSINIT_IMG is used for the system early initialization,
+# such as AVS settings, clock-tree setup and dynamic DDR PHY training.
+# After the initialization is done, this image will be wiped out
+# from the memory and CM3 will continue with RTOS image or other application.
+WTMI_SYSINIT_IMG       := $(DOIMAGEPATH)/wtmi/sys_init/build/sys_init.bin
+
+# WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG)
+# and sys-init image (WTMI_SYSINIT_IMG).
+WTMI_MULTI_IMG         := $(DOIMAGEPATH)/wtmi/build/wtmi.bin
+
+WTMI_ENC_IMG           := $(DOIMAGEPATH)/wtmi/build/wtmi-enc.bin
+BUILD_UART             := uart-images
+
+SRCPATH                        := $(dir $(BL33))
+
+CLOCKSPRESET           ?= CPU_800_DDR_800
+
+DDR_TOPOLOGY           ?= 0
+
+BOOTDEV                        ?= SPINOR
+PARTNUM                        ?= 0
+
+TIM_IMAGE              := $$(grep "Image Filename:" -m 1 $(DOIMAGE_CFG) | cut -c 17-)
+TIMBLDARGS             := $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \
+                               $(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 1
+TIMBLDUARTARGS         := $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \
+                               $(DDR_TOPOLOGY) 0 0 $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 0
+DOIMAGE_FLAGS          := -r $(DOIMAGE_CFG) -v -D
+
+
+# GICV3
+$(eval $(call add_define,CONFIG_GICV3))
+
+# CCI-400
+$(eval $(call add_define,USE_CCI))
+
+MARVELL_GIC_SOURCES    :=      drivers/arm/gic/common/gic_common.c     \
+                               drivers/arm/gic/v3/gicv3_main.c         \
+                               drivers/arm/gic/v3/gicv3_helpers.c      \
+                               drivers/arm/gic/v3/arm_gicv3_common.c   \
+                               plat/common/plat_gicv3.c                \
+                               drivers/arm/gic/v3/gic500.c
+
+ATF_INCLUDES           :=      -Iinclude/common/tbbr           \
+                               -Iinclude/drivers
+
+PLAT_INCLUDES          :=      -I$(PLAT_FAMILY_BASE)/$(PLAT)           \
+                               -I$(PLAT_COMMON_BASE)/include           \
+                               -I$(PLAT_INCLUDE_BASE)/common           \
+                               -I$(MARVELL_DRV_BASE)/uart              \
+                               -I$(MARVELL_DRV_BASE)                   \
+                               -I$/drivers/arm/gic/common/             \
+                               $(ATF_INCLUDES)
+
+PLAT_BL_COMMON_SOURCES :=      $(PLAT_COMMON_BASE)/aarch64/a3700_common.c \
+                               drivers/console/aarch64/console.S          \
+                               $(MARVELL_COMMON_BASE)/marvell_cci.c       \
+                               $(MARVELL_DRV_BASE)/uart/a3700_console.S
+
+BL1_SOURCES            +=      $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
+                               lib/cpus/aarch64/cortex_a53.S
+
+BL31_PORTING_SOURCES   :=      $(PLAT_FAMILY_BASE)/$(PLAT)/board/pm_src.c
+
+MARVELL_DRV            :=      $(MARVELL_DRV_BASE)/comphy/phy-comphy-3700.c
+
+BL31_SOURCES           +=      lib/cpus/aarch64/cortex_a53.S           \
+                               $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
+                               $(PLAT_COMMON_BASE)/plat_pm.c           \
+                               $(PLAT_COMMON_BASE)/dram_win.c          \
+                               $(PLAT_COMMON_BASE)/io_addr_dec.c       \
+                               $(PLAT_COMMON_BASE)/marvell_plat_config.c     \
+                               $(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \
+                               $(MARVELL_COMMON_BASE)/marvell_ddr_info.c       \
+                               $(MARVELL_COMMON_BASE)/marvell_gicv3.c  \
+                               $(MARVELL_GIC_SOURCES)                  \
+                               drivers/arm/cci/cci.c                   \
+                               $(BL31_PORTING_SOURCES)                 \
+                               $(PLAT_COMMON_BASE)/a3700_sip_svc.c     \
+                               $(MARVELL_DRV)
+
+mrvl_flash: ${BUILD_PLAT}/${FIP_NAME} ${DOIMAGETOOL}
+       $(shell truncate -s %128K ${BUILD_PLAT}/bl1.bin)
+       $(shell cat ${BUILD_PLAT}/bl1.bin ${BUILD_PLAT}/${FIP_NAME} > ${BUILD_PLAT}/${BOOT_IMAGE})
+       $(shell truncate -s %4 ${BUILD_PLAT}/${BOOT_IMAGE})
+       $(shell truncate -s %4 $(WTMI_IMG))
+       @echo
+       @echo "Building uart images"
+       $(TIMBUILD) $(TIMBLDUARTARGS)
+       @sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(DOIMAGE_CFG)
+       @sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(DOIMAGE_CFG)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+       @sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(TIMNCFG)
+       @sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(TIMNCFG)
+endif
+       $(DOIMAGETOOL) $(DOIMAGE_FLAGS)
+       @if [ -e "$(TIMNCFG)" ]; then $(DOIMAGETOOL) -r $(TIMNCFG); fi
+       @rm -rf $(BUILD_PLAT)/$(BUILD_UART)*
+       @mkdir $(BUILD_PLAT)/$(BUILD_UART)
+       @mv -t $(BUILD_PLAT)/$(BUILD_UART) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG)
+       @find . -name "*_h.*" |xargs cp -ut $(BUILD_PLAT)/$(BUILD_UART)
+       @mv $(subst .bin,_h.bin,$(WTMI_MULTI_IMG)) $(BUILD_PLAT)/$(BUILD_UART)/wtmi_h.bin
+       @tar czf $(BUILD_PLAT)/$(BUILD_UART).tgz -C $(BUILD_PLAT) ./$(BUILD_UART)
+       @echo
+       @echo "Building flash image"
+       $(TIMBUILD) $(TIMBLDARGS)
+       sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(DOIMAGE_CFG)
+       sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(DOIMAGE_CFG)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+       @sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(TIMNCFG)
+       @sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(TIMNCFG)
+       @echo -e "\n\t=======================================================\n";
+       @echo -e "\t  Secure boot. Encrypting wtmi and boot-image \n";
+       @echo -e "\t=======================================================\n";
+       @truncate -s %16 $(WTMI_MULTI_IMG)
+       @openssl enc -aes-256-cbc -e -in $(WTMI_MULTI_IMG) \
+       -out $(WTMI_ENC_IMG) \
+       -K `cat $(IMAGESPATH)/aes-256.txt` -k 0 -nosalt \
+       -iv `cat $(IMAGESPATH)/iv.txt` -p
+       @truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE);
+       @openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \
+       -out $(BUILD_PLAT)/$(BOOT_ENC_IMAGE) \
+       -K `cat $(IMAGESPATH)/aes-256.txt` -k 0 -nosalt \
+       -iv `cat $(IMAGESPATH)/iv.txt` -p
+endif
+       $(DOIMAGETOOL) $(DOIMAGE_FLAGS)
+       @if [ -e "$(TIMNCFG)" ]; then $(DOIMAGETOOL) -r $(TIMNCFG); fi
+       @if [ "$(MARVELL_SECURE_BOOT)" = "1" ]; then sed -i 's|$(WTMI_MULTI_IMG)|$(WTMI_ENC_IMG)|1;s|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1;' $(TIMNCFG); fi
+       $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE)
+       @mv -t $(BUILD_PLAT) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG) $(WTMI_IMG) $(WTMI_SYSINIT_IMG) $(WTMI_MULTI_IMG)
+       @if [ "$(MARVELL_SECURE_BOOT)" = "1" ]; then mv -t $(BUILD_PLAT) $(WTMI_ENC_IMG) OtpHash.txt; fi
+       @find . -name "*.txt" | grep -E "CSK[[:alnum:]]_KeyHash.txt|Tim_msg.txt|TIMHash.txt" | xargs rm -f
diff --git a/plat/marvell/a3700/common/a3700_sip_svc.c b/plat/marvell/a3700/common/a3700_sip_svc.c
new file mode 100644 (file)
index 0000000..88d1fc2
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <debug.h>
+#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
+#include <runtime_svc.h>
+#include <smccc.h>
+#include "comphy/phy-comphy-3700.h"
+
+/* Comphy related FID's */
+#define MV_SIP_COMPHY_POWER_ON 0x82000001
+#define MV_SIP_COMPHY_POWER_OFF        0x82000002
+#define MV_SIP_COMPHY_PLL_LOCK 0x82000003
+
+/* Miscellaneous FID's' */
+#define MV_SIP_DRAM_SIZE       0x82000010
+
+/* This macro is used to identify COMPHY related calls from SMC function ID */
+#define is_comphy_fid(fid)     \
+       ((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_PLL_LOCK)
+
+uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
+                              u_register_t x1,
+                              u_register_t x2,
+                              u_register_t x3,
+                              u_register_t x4,
+                              void *cookie,
+                              void *handle,
+                              u_register_t flags)
+{
+       u_register_t ret;
+
+       VERBOSE("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx\n",
+               __func__, smc_fid, x1, x2);
+       if (is_comphy_fid(smc_fid)) {
+               if (x1 >= MAX_LANE_NR) {
+                       ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n",
+                             __func__, smc_fid, x2);
+                       SMC_RET1(handle, SMC_UNK);
+               }
+       }
+
+       switch (smc_fid) {
+       /* Comphy related FID's */
+       case MV_SIP_COMPHY_POWER_ON:
+               /* x1: comphy_index, x2: comphy_mode */
+               ret = mvebu_3700_comphy_power_on(x1, x2);
+               SMC_RET1(handle, ret);
+       case MV_SIP_COMPHY_POWER_OFF:
+               /* x1: comphy_index, x2: comphy_mode */
+               ret = mvebu_3700_comphy_power_off(x1, x2);
+               SMC_RET1(handle, ret);
+       case MV_SIP_COMPHY_PLL_LOCK:
+               /* x1: comphy_index, x2: comphy_mode */
+               ret = mvebu_3700_comphy_is_pll_locked(x1, x2);
+               SMC_RET1(handle, ret);
+       /* Miscellaneous FID's' */
+       case MV_SIP_DRAM_SIZE:
+               /* x1:  ap_base_addr */
+               ret = mvebu_get_dram_size(MVEBU_REGS_BASE);
+               SMC_RET1(handle, ret);
+
+       default:
+               ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+               SMC_RET1(handle, SMC_UNK);
+       }
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+       marvell_sip_svc,
+       OEN_SIP_START,
+       OEN_SIP_END,
+       SMC_TYPE_FAST,
+       NULL,
+       mrvl_sip_smc_handler
+);
diff --git a/plat/marvell/a3700/common/aarch64/a3700_common.c b/plat/marvell/a3700/common/aarch64/a3700_common.c
new file mode 100644 (file)
index 0000000..6351285
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+#include <plat_marvell.h>
+
+/* MMU entry for internal (register) space access */
+#define MAP_DEVICE0    MAP_REGION_FLAT(DEVICE0_BASE,                   \
+                                       DEVICE0_SIZE,                   \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_marvell_mmap[] = {
+       MARVELL_MAP_SHARED_RAM,
+       MAP_DEVICE0,
+       {0}
+};
+#endif
+#if IMAGE_BL2
+const mmap_region_t plat_marvell_mmap[] = {
+       MARVELL_MAP_SHARED_RAM,
+       MAP_DEVICE0,
+       MARVELL_MAP_DRAM,
+       {0}
+};
+#endif
+#if IMAGE_BL2U
+const mmap_region_t plat_marvell_mmap[] = {
+       MAP_DEVICE0,
+       {0}
+};
+#endif
+#if IMAGE_BL31
+const mmap_region_t plat_marvell_mmap[] = {
+       MARVELL_MAP_SHARED_RAM,
+       MAP_DEVICE0,
+       MARVELL_MAP_DRAM,
+       {0}
+};
+#endif
+#if IMAGE_BL32
+const mmap_region_t plat_marvell_mmap[] = {
+       MAP_DEVICE0,
+       {0}
+};
+#endif
+
+MARVELL_CASSERT_MMAP;
diff --git a/plat/marvell/a3700/common/aarch64/plat_helpers.S b/plat/marvell/a3700/common/aarch64/plat_helpers.S
new file mode 100644 (file)
index 0000000..90d76f0
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+
+       .globl  plat_secondary_cold_boot_setup
+       .globl  plat_get_my_entrypoint
+       .globl  plat_is_my_cpu_primary
+
+       /* -----------------------------------------------------
+        * void plat_secondary_cold_boot_setup (void);
+        *
+        * This function performs any platform specific actions
+        * needed for a secondary cpu after a cold reset. Right
+        * now this is a stub function.
+        * -----------------------------------------------------
+        */
+func plat_secondary_cold_boot_setup
+       mov     x0, #0
+       ret
+endfunc plat_secondary_cold_boot_setup
+
+       /* ---------------------------------------------------------------------
+        * unsigned long plat_get_my_entrypoint (void);
+        *
+        * Main job of this routine is to distinguish between cold and warm boot
+        * For a cold boot, return 0.
+        * For a warm boot, read the mailbox and return the address it contains.
+        * A magic number is placed before entrypoint to avoid mistake caused by
+        * uninitialized mailbox data area.
+        * ---------------------------------------------------------------------
+        */
+func plat_get_my_entrypoint
+       /* Read first word and compare it with magic num */
+       mov_imm x0, PLAT_MARVELL_MAILBOX_BASE
+       ldr     x1, [x0]
+       mov_imm x2, PLAT_MARVELL_MAILBOX_MAGIC_NUM
+       cmp     x1, x2
+       /* If compare failed, return 0, i.e. cold boot */
+       beq     entrypoint
+       mov     x0, #0
+       ret
+entrypoint:
+       /* Second word contains the jump address */
+       add     x0, x0, #8
+       ldr     x0, [x0]
+       ret
+endfunc plat_get_my_entrypoint
+
+       /* -----------------------------------------------------
+        * unsigned int plat_is_my_cpu_primary (void);
+        *
+        * Find out whether the current cpu is the primary
+        * cpu.
+        * -----------------------------------------------------
+        */
+func plat_is_my_cpu_primary
+       mrs     x0, mpidr_el1
+       and     x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+       cmp     x0, #MVEBU_PRIMARY_CPU
+       cset    w0, eq
+       ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/marvell/a3700/common/dram_win.c b/plat/marvell/a3700/common/dram_win.c
new file mode 100644 (file)
index 0000000..fb236d8
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <dram_win.h>
+#include <marvell_plat_priv.h>
+#include <mmio.h>
+#include <mvebu.h>
+#include <plat_marvell.h>
+#include <string.h>
+
+/* Armada 3700 has 5 configurable windows */
+#define MV_CPU_WIN_NUM         5
+
+#define CPU_WIN_DISABLED       0
+#define CPU_WIN_ENABLED                1
+
+/*
+ * There are 2 different cpu decode window configuration cases:
+ * - DRAM size is not over 2GB;
+ * - DRAM size is 4GB.
+ */
+enum cpu_win_config_num {
+       CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB = 0,
+       CPU_WIN_CONFIG_DRAM_4GB,
+       CPU_WIN_CONFIG_MAX
+};
+
+enum cpu_win_target {
+       CPU_WIN_TARGET_DRAM = 0,
+       CPU_WIN_TARGET_INTERNAL_REG,
+       CPU_WIN_TARGET_PCIE,
+       CPU_WIN_TARGET_PCIE_OVER_MCI,
+       CPU_WIN_TARGET_BOOT_ROM,
+       CPU_WIN_TARGET_MCI_EXTERNAL,
+       CPU_WIN_TARGET_RWTM_RAM = 7,
+       CPU_WIN_TARGET_CCI400_REG
+};
+
+struct cpu_win_configuration {
+       uint32_t                enabled;
+       enum cpu_win_target     target;
+       uint64_t                base_addr;
+       uint64_t                size;
+       uint64_t                remap_addr;
+};
+
+struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = {
+       /*
+        * When total dram size is not over 2GB:
+        * DDR window 0 is configured in tim header, its size may be not 512MB,
+        * but the actual dram size, no need to configure it again;
+        * other cpu windows are kept as default.
+        */
+       {
+               /* enabled
+                *      target
+                *              base
+                *                      size
+                *                              remap
+                */
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_DRAM,
+                               0x0,
+                                       0x08000000,
+                                               0x0},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_MCI_EXTERNAL,
+                               0xe0000000,
+                                       0x08000000,
+                                               0xe0000000},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_PCIE,
+                               0xe8000000,
+                                       0x08000000,
+                                               0xe8000000},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_RWTM_RAM,
+                               0xf0000000,
+                                       0x00020000,
+                                               0x1fff0000},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_PCIE_OVER_MCI,
+                               0x80000000,
+                                       0x10000000,
+                                               0x80000000},
+       },
+
+       /*
+        * If total dram size is more than 2GB, now there is only one case - 4GB
+        *  dram; we will use below cpu windows configurations:
+        *  - Internal Regs, CCI-400, Boot Rom and PCIe windows are kept as
+        *    default;
+        *  - Use 4 CPU decode windows for DRAM, which cover 3.375GB DRAM;
+        *    DDR window 0 is configured in tim header with 2GB size, no need to
+        *    configure it again here;
+        *
+        *      0xFFFFFFFF ---> |-----------------------|
+        *                      |         Boot ROM      | 64KB
+        *      0xFFF00000 ---> +-----------------------+
+        *                      :                       :
+        *      0xF0000000 ---> |-----------------------|
+        *                      |         PCIE          | 128 MB
+        *      0xE8000000 ---> |-----------------------|
+        *                      |         DDR window 3  | 128 MB
+        *      0xE0000000 ---> +-----------------------+
+        *                      :                       :
+        *      0xD8010000 ---> |-----------------------|
+        *                      |         CCI Regs      | 64 KB
+        *      0xD8000000 ---> +-----------------------+
+        *                      :                       :
+        *                      :                       :
+        *      0xD2000000 ---> +-----------------------+
+        *                      |        Internal Regs  | 32MB
+        *      0xD0000000 ---> |-----------------------|
+        *                       |        DDR window 2  | 256 MB
+        *      0xC0000000 ---> |-----------------------|
+        *                      |                       |
+        *                      |        DDR window 1   | 1 GB
+        *                      |                       |
+        *      0x80000000 ---> |-----------------------|
+        *                      |                       |
+        *                      |                       |
+        *                      |        DDR window 0   | 2 GB
+        *                      |                       |
+        *                      |                       |
+        *      0x00000000 ---> +-----------------------+
+        */
+       {
+               /* win_id
+                *      target
+                *              base
+                *                      size
+                *                              remap
+                */
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_DRAM,
+                               0x0,
+                                       0x80000000,
+                                               0x0},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_DRAM,
+                               0x80000000,
+                                       0x40000000,
+                                               0x80000000},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_DRAM,
+                               0xc0000000,
+                                       0x10000000,
+                                               0xc0000000},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_DRAM,
+                               0xe0000000,
+                                       0x08000000,
+                                               0xe0000000},
+               {CPU_WIN_ENABLED,
+                       CPU_WIN_TARGET_PCIE,
+                               0xe8000000,
+                                       0x08000000,
+                                               0xe8000000},
+       },
+};
+
+/*
+ * dram_win_map_build
+ *
+ * This function builds cpu dram windows mapping
+ * which includes base address and window size by
+ * reading cpu dram decode windows registers.
+ *
+ * @input: N/A
+ *
+ * @output:
+ *     - win_map: cpu dram windows mapping
+ *
+ * @return:  N/A
+ */
+void dram_win_map_build(struct dram_win_map *win_map)
+{
+       int32_t win_id;
+       struct dram_win *win;
+       uint32_t base_reg, ctrl_reg, size_reg, enabled, target;
+
+       memset(win_map, 0, sizeof(struct dram_win_map));
+       for (win_id = 0; win_id < DRAM_WIN_MAP_NUM_MAX; win_id++) {
+               ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
+               target = (ctrl_reg & CPU_DEC_CR_WIN_TARGET_MASK) >>
+                         CPU_DEC_CR_WIN_TARGET_OFFS;
+               enabled = ctrl_reg & CPU_DEC_CR_WIN_ENABLE;
+               /* Ignore invalid and non-dram windows*/
+               if ((enabled == 0) || (target != DRAM_CPU_DEC_TARGET_NUM))
+                       continue;
+
+               win = win_map->dram_windows + win_map->dram_win_num;
+               base_reg = mmio_read_32(CPU_DEC_WIN_BASE_REG(win_id));
+               size_reg = mmio_read_32(CPU_DEC_WIN_SIZE_REG(win_id));
+               /* Base reg [15:0] corresponds to transaction address [39:16] */
+               win->base_addr = (base_reg & CPU_DEC_BR_BASE_MASK) >>
+                                 CPU_DEC_BR_BASE_OFFS;
+               win->base_addr *= CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
+               /*
+                * Size reg [15:0] is programmed from LSB to MSB as a sequence
+                * of 1s followed by a sequence of 0s and the number of 1s
+                * specifies the size of the window in 64 KB granularity,
+                * for example, a value of 00FFh specifies 256 x 64 KB = 16 MB
+                */
+               win->win_size = (size_reg & CPU_DEC_CR_WIN_SIZE_MASK) >>
+                                CPU_DEC_CR_WIN_SIZE_OFFS;
+               win->win_size = (win->win_size + 1) *
+                                CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
+
+               win_map->dram_win_num++;
+       }
+}
+
+static void cpu_win_set(uint32_t win_id, struct cpu_win_configuration *win_cfg)
+{
+       uint32_t base_reg, ctrl_reg, size_reg, remap_reg;
+
+       /* Disable window */
+       ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
+       ctrl_reg &= ~CPU_DEC_CR_WIN_ENABLE;
+       mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
+
+       /* For an disabled window, only disable it. */
+       if (!win_cfg->enabled)
+               return;
+
+       /* Set Base Register */
+       base_reg = (uint32_t)(win_cfg->base_addr /
+                  CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
+       base_reg <<= CPU_DEC_BR_BASE_OFFS;
+       base_reg &= CPU_DEC_BR_BASE_MASK;
+       mmio_write_32(CPU_DEC_WIN_BASE_REG(win_id), base_reg);
+
+       /* Set Remap Register with the same value
+        * as the <Base> field in Base Register
+        */
+       remap_reg = (uint32_t)(win_cfg->remap_addr /
+                   CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
+       remap_reg <<= CPU_DEC_RLR_REMAP_LOW_OFFS;
+       remap_reg &= CPU_DEC_RLR_REMAP_LOW_MASK;
+       mmio_write_32(CPU_DEC_REMAP_LOW_REG(win_id), remap_reg);
+
+       /* Set Size Register */
+       size_reg = (win_cfg->size / CPU_DEC_CR_WIN_SIZE_ALIGNMENT) - 1;
+       size_reg <<= CPU_DEC_CR_WIN_SIZE_OFFS;
+       size_reg &= CPU_DEC_CR_WIN_SIZE_MASK;
+       mmio_write_32(CPU_DEC_WIN_SIZE_REG(win_id), size_reg);
+
+       /* Set Control Register - set target id and enable window */
+       ctrl_reg &= ~CPU_DEC_CR_WIN_TARGET_MASK;
+       ctrl_reg |= (win_cfg->target << CPU_DEC_CR_WIN_TARGET_OFFS);
+       ctrl_reg |= CPU_DEC_CR_WIN_ENABLE;
+       mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
+}
+
+void cpu_wins_init(void)
+{
+       uint32_t cfg_idx, win_id;
+
+       if (mvebu_get_dram_size(MVEBU_REGS_BASE) <= _2GB_)
+               cfg_idx = CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB;
+       else
+               cfg_idx = CPU_WIN_CONFIG_DRAM_4GB;
+
+       /* Window 0 is configured always for DRAM in tim header
+        * already, no need to configure it again here
+        */
+       for (win_id = 1; win_id < MV_CPU_WIN_NUM; win_id++)
+               cpu_win_set(win_id, &mv_cpu_wins[cfg_idx][win_id]);
+}
+
diff --git a/plat/marvell/a3700/common/include/a3700_plat_def.h b/plat/marvell/a3700/common/include/a3700_plat_def.h
new file mode 100644 (file)
index 0000000..6ae57b3
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __A3700_PLAT_DEF_H__
+#define __A3700_PLAT_DEF_H__
+
+#include <marvell_def.h>
+
+
+#define MVEBU_MAX_CPUS_PER_CLUSTER     2
+
+#define MVEBU_PRIMARY_CPU              0x0
+
+/*
+ * The counter on A3700 is always fed from reference 25M clock (XTAL).
+ * However minimal CPU counter prescaler is 2, so the counter
+ * frequency will be divided by 2, the number is 12.5M
+ */
+#define COUNTER_FREQUENCY              12500000
+
+#define MVEBU_REGS_BASE                        0xD0000000
+
+/*****************************************************************************
+ * MVEBU memory map related constants
+ *****************************************************************************
+ */
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE                   MVEBU_REGS_BASE
+#define DEVICE0_SIZE                   0x10000000
+
+/*****************************************************************************
+ * GIC-500 & interrupt handling related constants
+ *****************************************************************************
+ */
+/* Base MVEBU compatible GIC memory map */
+#define MVEBU_GICD_BASE                        0x1D00000
+#define MVEBU_GICR_BASE                        0x1D40000
+#define MVEBU_GICC_BASE                        0x1D80000
+
+/* CCI-400 */
+#define MVEBU_CCI_BASE                 0x8000000
+
+/*****************************************************************************
+ * North and south bridge register base
+ *****************************************************************************
+ */
+#define MVEBU_NB_REGS_BASE                     (MVEBU_REGS_BASE + 0x13000)
+#define MVEBU_SB_REGS_BASE                     (MVEBU_REGS_BASE + 0x18000)
+
+/*****************************************************************************
+ * GPIO registers related constants
+ *****************************************************************************
+ */
+/* North and south bridge GPIO register base address */
+#define MVEBU_NB_GPIO_REG_BASE                 (MVEBU_NB_REGS_BASE + 0x800)
+#define MVEBU_NB_GPIO_IRQ_REG_BASE             (MVEBU_NB_REGS_BASE + 0xC00)
+#define MVEBU_SB_GPIO_REG_BASE                 (MVEBU_SB_REGS_BASE + 0x800)
+#define MVEBU_SB_GPIO_IRQ_REG_BASE             (MVEBU_SB_REGS_BASE + 0xC00)
+#define MVEBU_NB_SB_IRQ_REG_BASE               (MVEBU_REGS_BASE + 0x8A00)
+
+/* North Bridge GPIO selection register */
+#define MVEBU_NB_GPIO_SEL_REG                  (MVEBU_NB_GPIO_REG_BASE + 0x30)
+#define MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG       (MVEBU_NB_GPIO_REG_BASE + 0x04)
+/* I2C1 GPIO Enable bit offset */
+#define MVEBU_GPIO_TW1_GPIO_EN_OFF             (10)
+/* SPI pins mode bit offset */
+#define MVEBU_GPIO_NB_SPI_PIN_MODE_OFF         (28)
+
+/*****************************************************************************
+ * DRAM registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_DRAM_REG_BASE                    (MVEBU_REGS_BASE)
+
+/*****************************************************************************
+ * SB wake-up registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_SB_WAKEUP_REG_BASE               (MVEBU_REGS_BASE + 0x19000)
+
+/*****************************************************************************
+ * PMSU registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_PMSU_REG_BASE                    (MVEBU_REGS_BASE + 0x14000)
+
+/*****************************************************************************
+ * North Bridge Step-Down Registers
+ *****************************************************************************
+ */
+#define MVEBU_NB_STEP_DOWN_REG_BASE            (MVEBU_REGS_BASE + 0x12800)
+
+/*****************************************************************************
+ * DRAM CS memory map register base
+ *****************************************************************************
+ */
+#define MVEBU_CS_MMAP_REG_BASE                 (MVEBU_REGS_BASE + 0x200)
+
+/*****************************************************************************
+ * CPU decoder window registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_CPU_DEC_WIN_REG_BASE             (MVEBU_REGS_BASE + 0xCF00)
+
+/*****************************************************************************
+ * AVS registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_AVS_REG_BASE                     (MVEBU_REGS_BASE + 0x11500)
+
+
+/*****************************************************************************
+ * AVS registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_COMPHY_REG_BASE                  (MVEBU_REGS_BASE + 0x18300)
+
+#endif /* __A3700_PLAT_DEF_H__ */
diff --git a/plat/marvell/a3700/common/include/a3700_pm.h b/plat/marvell/a3700/common/include/a3700_pm.h
new file mode 100644 (file)
index 0000000..bd8792a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __A3700_PM_H__
+#define __A3700_PM_H__
+
+#include <stdint.h>
+
+/* supported wake up sources */
+enum pm_wake_up_src_type {
+       WAKE_UP_SRC_GPIO,
+       /* FOLLOWING SRC NOT SUPPORTED YET */
+       WAKE_UP_SRC_TIMER,
+       WAKE_UP_SRC_UART0,
+       WAKE_UP_SRC_UART1,
+       WAKE_UP_SRC_MAX,
+};
+
+struct pm_gpio_data {
+       /*
+        * bank 0: North bridge GPIO
+        * bank 1: South bridge GPIO
+        */
+       uint32_t bank_num;
+       uint32_t gpio_num;
+};
+
+union pm_wake_up_src_data {
+       struct pm_gpio_data gpio_data;
+       /* delay in seconds */
+       uint32_t timer_delay;
+};
+
+struct pm_wake_up_src {
+       enum pm_wake_up_src_type wake_up_src_type;
+
+       union pm_wake_up_src_data wake_up_data;
+};
+
+struct pm_wake_up_src_config {
+       uint32_t        wake_up_src_num;
+       struct pm_wake_up_src wake_up_src[WAKE_UP_SRC_MAX];
+};
+
+struct pm_wake_up_src_config *mv_wake_up_src_config_get(void);
+
+
+#endif /* __A3700_PM_H__ */
diff --git a/plat/marvell/a3700/common/include/ddr_info.h b/plat/marvell/a3700/common/include/ddr_info.h
new file mode 100644 (file)
index 0000000..1a9230d
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef _DDR_INFO_H_
+#define _DDR_INFO_H_
+
+#define DRAM_MAX_IFACE                 1
+#define DRAM_CH0_MMAP_LOW_OFFSET       0x200
+
+#endif /* _DDR_INFO_H_ */
diff --git a/plat/marvell/a3700/common/include/dram_win.h b/plat/marvell/a3700/common/include/dram_win.h
new file mode 100644 (file)
index 0000000..7ff20be
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef _DRAM_WIN_H_
+#define _DRAM_WIN_H_
+
+#include <bl_common.h>
+#include <io_addr_dec.h>
+
+void dram_win_map_build(struct dram_win_map *win_map);
+void cpu_wins_init(void);
+
+#endif /* _DRAM_WIN_H_ */
+
diff --git a/plat/marvell/a3700/common/include/io_addr_dec.h b/plat/marvell/a3700/common/include/io_addr_dec.h
new file mode 100644 (file)
index 0000000..79f6f2c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef _IO_ADDR_DEC_H_
+#define _IO_ADDR_DEC_H_
+
+#include <stdint.h>
+
+/* There are 5 configurable cpu decoder windows. */
+#define DRAM_WIN_MAP_NUM_MAX   5
+/* Target number for dram in cpu decoder windows. */
+#define DRAM_CPU_DEC_TARGET_NUM        0
+
+/*
+ * Not all configurable decode windows could be used for dram, some units have
+ * to reserve one decode window for other unit they have to communicate with;
+ * for example, DMA engineer has 3 configurable windows, but only two could be
+ * for dram while the last one has to be for pcie, so for DMA, its max_dram_win
+ * is 2.
+ */
+struct dec_win_config {
+       uint32_t dec_reg_base; /* IO address decoder register base address */
+       uint32_t win_attr;      /* IO address decoder windows attributes */
+       /* How many configurable dram decoder windows that this unit has; */
+       uint32_t max_dram_win;
+       /* The decoder windows number including remapping that this unit has */
+       uint32_t max_remap;
+       /* The offset between continuous decode windows
+        * within the same unit, typically 0x10
+        */
+       uint32_t win_offset;
+};
+
+struct dram_win {
+       uintptr_t base_addr;
+       uintptr_t win_size;
+};
+
+struct  dram_win_map {
+       int dram_win_num;
+       struct dram_win dram_windows[DRAM_WIN_MAP_NUM_MAX];
+};
+
+/*
+ * init_io_addr_dec
+ *
+ * This function initializes io address decoder windows by
+ * cpu dram window mapping information
+ *
+ * @input: N/A
+ *     - dram_wins_map: cpu dram windows mapping
+ *     - io_dec_config: io address decoder windows configuration
+ *     - io_unit_num: io address decoder unit number
+ * @output: N/A
+ *
+ * @return:  0 on success and others on failure
+ */
+int init_io_addr_dec(struct dram_win_map *dram_wins_map,
+                    struct dec_win_config *io_dec_config,
+                    uint32_t io_unit_num);
+
+#endif /* _IO_ADDR_DEC_H_ */
+
diff --git a/plat/marvell/a3700/common/include/plat_macros.S b/plat/marvell/a3700/common/include/plat_macros.S
new file mode 100644 (file)
index 0000000..b52d1cf
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <marvell_macros.S>
+
+/* ---------------------------------------------
+ * The below macro prints out relevant GIC and
+ * CCI registers registers whenever an unhandled
+ * exception is taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+       mov_imm x17, MVEBU_GICC_BASE
+       mov_imm x16, MVEBU_GICD_BASE
+       marvell_print_gic_regs
+       print_cci_regs
+.endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/marvell/a3700/common/include/platform_def.h b/plat/marvell/a3700/common/include/platform_def.h
new file mode 100644 (file)
index 0000000..7c72cc5
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <board_marvell_def.h>
+#include <mvebu_def.h>
+#ifndef __ASSEMBLY__
+#include <stdio.h>
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Most platform porting definitions provided by included headers
+ */
+
+/*
+ * DRAM Memory layout:
+ *             +-----------------------+
+ *             :                       :
+ *             :       Linux           :
+ * 0x04X00000-->+-----------------------+
+ *             |       BL3-3(u-boot)   |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ *             |-----------------------|  }                                   |
+ *             |       BL3-[0,1, 2]    |  }---------------------------------> |
+ *             |-----------------------|  }                            ||     |
+ *             |       BL2             |  }->FIP (loaded by            ||     |
+ *             |-----------------------|  }       BootROM to DRAM)     ||     |
+ *             |       FIP_TOC         |  }                            ||     |
+ * 0x04120000-->|-----------------------|                              ||     |
+ *             |       BL1 (RO)        |                               ||     |
+ * 0x04100000-->+-----------------------+                              ||     |
+ *             :                       :                               ||     |
+ *             : Trusted SRAM section  :                               \/     |
+ * 0x04040000-->+-----------------------+  Replaced by BL2  +----------------+ |
+ *             |       BL1 (RW)        |  <<<<<<<<<<<<<<<< | BL3-1 NOBITS   | |
+ * 0x04037000-->|-----------------------|  <<<<<<<<<<<<<<<< |----------------| |
+ *             |                       |  <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | |
+ * 0x04023000-->|-----------------------|                  +----------------+ |
+ *             |       BL2             |                                      |
+ *             |-----------------------|                                      |
+ *             |                       |                                      |
+ * 0x04001000-->|-----------------------|                                     |
+ *             |       Shared          |                                      |
+ * 0x04000000-->+-----------------------+                                     |
+ *             :                       :                                      |
+ *             :       Linux           :                                      |
+ *             :                       :                                      |
+ *             |-----------------------|                                      |
+ *             |                       |       U-Boot(BL3-3) Loaded by BL2    |
+ *             |       U-Boot          |       <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ * 0x00000000-->+-----------------------+
+ *
+ * Trusted SRAM section 0x4000000..0x4200000:
+ * ----------------------------------------
+ * SRAM_BASE           = 0x4001000
+ * BL2_BASE            = 0x4006000
+ * BL2_LIMIT           = BL31_BASE
+ * BL31_BASE           = 0x4023000 = (64MB + 256KB - 0x1D000)
+ * BL31_PROGBITS_LIMIT = BL1_RW_BASE
+ * BL1_RW_BASE         = 0x4037000 = (64MB + 256KB - 0x9000)
+ * BL1_RW_LIMIT                = BL31_LIMIT = 0x4040000
+ *
+ *
+ * PLAT_MARVELL_FIP_BASE       = 0x4120000
+ */
+
+#define PLAT_MARVELL_ATF_BASE                  0x4000000
+#define PLAT_MARVELL_ATF_LOAD_ADDR             \
+                       (PLAT_MARVELL_ATF_BASE + 0x100000)
+
+#define PLAT_MARVELL_FIP_BASE                  \
+                       (PLAT_MARVELL_ATF_LOAD_ADDR + 0x20000)
+#define PLAT_MARVELL_FIP_MAX_SIZE              0x4000000
+
+#define PLAT_MARVELL_CLUSTER_CORE_COUNT                2
+/* DRAM[2MB..66MB] is used  as Trusted ROM */
+#define PLAT_MARVELL_TRUSTED_ROM_BASE          PLAT_MARVELL_ATF_LOAD_ADDR
+/* 64 MB TODO: reduce this to minimum needed according to fip image size*/
+#define PLAT_MARVELL_TRUSTED_ROM_SIZE          0x04000000
+/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
+#define PLAT_MARVELL_TRUSTED_DRAM_BASE         0x04400000
+#define PLAT_MARVELL_TRUSTED_DRAM_SIZE         0x01000000      /* 16 MB */
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_MARVELL_MAX_BL1_RW_SIZE           0xA000
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_MARVELL_MAX_BL2_SIZE              0xF000
+
+/*
+ * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_MARVEL_MAX_BL31_SIZE              0x5D000
+
+#define PLAT_MARVELL_CPU_ENTRY_ADDR            BL1_RO_BASE
+
+/* GIC related definitions */
+#define PLAT_MARVELL_GICD_BASE         (MVEBU_REGS_BASE + MVEBU_GICD_BASE)
+#define PLAT_MARVELL_GICR_BASE         (MVEBU_REGS_BASE + MVEBU_GICR_BASE)
+#define PLAT_MARVELL_GICC_BASE         (MVEBU_REGS_BASE + MVEBU_GICC_BASE)
+
+#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL), \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL)
+
+#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, \
+                       GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_LEVEL), \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL), \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL), \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL), \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL), \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL), \
+       INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+                       GIC_INTR_CFG_LEVEL)
+
+
+#define PLAT_MARVELL_SHARED_RAM_CACHED         1
+
+/* CCI related constants */
+#define PLAT_MARVELL_CCI_BASE          (MVEBU_REGS_BASE + MVEBU_CCI_BASE)
+#define PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX  3
+#define PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX  4
+
+/*
+ * Load address of BL3-3 for this platform port
+ */
+#define PLAT_MARVELL_NS_IMAGE_OFFSET           0x0
+
+/* System Reference Clock*/
+#define PLAT_REF_CLK_IN_HZ                     COUNTER_FREQUENCY
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_MARVELL_BOOT_UART_BASE            (MVEBU_REGS_BASE + 0x12000)
+#define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ       25804800
+
+#define PLAT_MARVELL_CRASH_UART_BASE           PLAT_MARVELL_BOOT_UART_BASE
+#define PLAT_MARVELL_CRASH_UART_CLK_IN_HZ      PLAT_MARVELL_BOOT_UART_CLK_IN_HZ
+
+#define PLAT_MARVELL_BL31_RUN_UART_BASE                PLAT_MARVELL_BOOT_UART_BASE
+#define PLAT_MARVELL_BL31_RUN_UART_CLK_IN_HZ   PLAT_MARVELL_BOOT_UART_CLK_IN_HZ
+
+/* Required platform porting definitions */
+#define PLAT_MAX_PWR_LVL                       MPIDR_AFFLVL1
+
+/* System timer related constants */
+#define PLAT_MARVELL_NSTIMER_FRAME_ID          1
+
+/* Mailbox base address */
+#define PLAT_MARVELL_MAILBOX_BASE              \
+                       (MARVELL_TRUSTED_SRAM_BASE + 0x400)
+#define PLAT_MARVELL_MAILBOX_SIZE              0x100
+#define PLAT_MARVELL_MAILBOX_MAGIC_NUM         0x6D72766C      /* mrvl */
+
+/* DRAM CS memory map registers related constants */
+#define MVEBU_CS_MMAP_LOW(cs_num)              \
+                       (MVEBU_CS_MMAP_REG_BASE + (cs_num) * 0x8)
+#define MVEBU_CS_MMAP_ENABLE                   0x1
+#define MVEBU_CS_MMAP_AREA_LEN_OFFS            16
+#define MVEBU_CS_MMAP_AREA_LEN_MASK            \
+                       (0x1f << MVEBU_CS_MMAP_AREA_LEN_OFFS)
+#define MVEBU_CS_MMAP_START_ADDR_LOW_OFFS      23
+#define MVEBU_CS_MMAP_START_ADDR_LOW_MASK      \
+                       (0x1ff << MVEBU_CS_MMAP_START_ADDR_LOW_OFFS)
+
+#define MVEBU_CS_MMAP_HIGH(cs_num)             \
+                       (MVEBU_CS_MMAP_REG_BASE + 0x4 + (cs_num) * 0x8)
+
+/* DRAM max CS number */
+#define MVEBU_MAX_CS_MMAP_NUM                  (2)
+
+/* CPU decoder window related constants */
+#define CPU_DEC_WIN_CTRL_REG(win_num)          \
+                       (MVEBU_CPU_DEC_WIN_REG_BASE + (win_num) * 0x10)
+#define CPU_DEC_CR_WIN_ENABLE                  0x1
+#define CPU_DEC_CR_WIN_TARGET_OFFS             4
+#define CPU_DEC_CR_WIN_TARGET_MASK             \
+                       (0xf << CPU_DEC_CR_WIN_TARGET_OFFS)
+
+#define CPU_DEC_WIN_SIZE_REG(win_num)          \
+                       (MVEBU_CPU_DEC_WIN_REG_BASE + 0x4 + (win_num) * 0x10)
+#define CPU_DEC_CR_WIN_SIZE_OFFS               0
+#define CPU_DEC_CR_WIN_SIZE_MASK               \
+                       (0xffff << CPU_DEC_CR_WIN_SIZE_OFFS)
+#define CPU_DEC_CR_WIN_SIZE_ALIGNMENT          0x10000
+
+#define CPU_DEC_WIN_BASE_REG(win_num)          \
+                       (MVEBU_CPU_DEC_WIN_REG_BASE + 0x8 + (win_num) * 0x10)
+#define CPU_DEC_BR_BASE_OFFS                   0
+#define CPU_DEC_BR_BASE_MASK                   \
+                       (0xffff <<  CPU_DEC_BR_BASE_OFFS)
+
+#define CPU_DEC_REMAP_LOW_REG(win_num)         \
+                       (MVEBU_CPU_DEC_WIN_REG_BASE + 0xC + (win_num) * 0x10)
+#define CPU_DEC_RLR_REMAP_LOW_OFFS             0
+#define CPU_DEC_RLR_REMAP_LOW_MASK             \
+                       (0xffff <<  CPU_DEC_BR_BASE_OFFS)
+
+/* Securities */
+#define IRQ_SEC_OS_TICK_INT    MARVELL_IRQ_SEC_PHY_TIMER
+
+#define TRUSTED_DRAM_BASE      PLAT_MARVELL_TRUSTED_DRAM_BASE
+#define TRUSTED_DRAM_SIZE      PLAT_MARVELL_TRUSTED_DRAM_SIZE
+
+#ifdef BL32
+#define BL32_BASE              TRUSTED_DRAM_BASE
+#define BL32_LIMIT             TRUSTED_DRAM_SIZE
+#endif
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/marvell/a3700/common/io_addr_dec.c b/plat/marvell/a3700/common/io_addr_dec.c
new file mode 100644 (file)
index 0000000..f009594
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+#include <debug.h>
+#include <io_addr_dec.h>
+#include <mmio.h>
+#include <plat_marvell.h>
+
+#define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
+                                               (win) * (off))
+#define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
+                                               (win) * (off) + 0x4)
+#define MVEBU_DEC_WIN_REMAP_REG(base, win, off)        (MVEBU_REGS_BASE + (base) + \
+                                               (win) * (off) + 0x8)
+
+#define MVEBU_DEC_WIN_CTRL_SIZE_OFF            (16)
+#define MVEBU_DEC_WIN_ENABLE                   (0x1)
+#define MVEBU_DEC_WIN_CTRL_ATTR_OFF            (8)
+#define MVEBU_DEC_WIN_CTRL_TARGET_OFF          (4)
+#define MVEBU_DEC_WIN_CTRL_EN_OFF              (0)
+#define MVEBU_DEC_WIN_BASE_OFF                 (16)
+
+#define MVEBU_WIN_BASE_SIZE_ALIGNMENT          (0x10000)
+
+/* There are up to 14 IO unit which need address decode in Armada-3700 */
+#define IO_UNIT_NUM_MAX                                (14)
+
+#define MVEBU_MAX_ADDRSS_4GB                   (0x100000000ULL)
+
+
+static void set_io_addr_dec_win(int win_id, uintptr_t base_addr,
+                               uintptr_t win_size,
+                               struct dec_win_config *dec_win)
+{
+       uint32_t ctrl = 0;
+       uint32_t base = 0;
+
+       /* set size */
+       ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) <<
+              MVEBU_DEC_WIN_CTRL_SIZE_OFF;
+       /* set attr according to IO decode window */
+       ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF;
+       /* set target */
+       ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF;
+       /* set base */
+       base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) <<
+              MVEBU_DEC_WIN_BASE_OFF;
+
+       /* set base address*/
+       mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
+                     win_id, dec_win->win_offset),
+                     base);
+       /* set remap window, some unit does not have remap window */
+       if (win_id < dec_win->max_remap)
+               mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
+                             win_id, dec_win->win_offset), base);
+       /* set control register */
+       mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
+                     win_id, dec_win->win_offset), ctrl);
+       /* enable the address decode window at last to make it effective */
+       ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF;
+       mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
+                     win_id, dec_win->win_offset), ctrl);
+
+       INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x)",
+            win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
+            win_id, dec_win->win_offset)),
+            mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
+                         win_id, dec_win->win_offset)));
+       if (win_id < dec_win->max_remap)
+               INFO(" remap(%x)\n",
+                    mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
+                    win_id, dec_win->win_offset)));
+       else
+               INFO("\n");
+}
+
+/* Set io decode window */
+static int set_io_addr_dec(struct dram_win_map *win_map,
+                          struct dec_win_config *dec_win)
+{
+       struct dram_win *win;
+       int id;
+
+       /* disable all windows first */
+       for (id = 0; id < dec_win->max_dram_win; id++)
+               mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id,
+                             dec_win->win_offset), 0);
+
+       /* configure IO decode windows for DRAM, inheritate DRAM size,
+        * base and target from CPU-DRAM decode window and others
+        * from hard coded IO decode window settings array.
+        */
+       if (win_map->dram_win_num > dec_win->max_dram_win) {
+               /*
+                * If cpu dram windows number exceeds the io decode windows
+                * max number, then fill the first io decode window
+                * with base(0) and size(4GB).
+                */
+               set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win);
+
+               return 0;
+       }
+
+       for (id = 0; id < win_map->dram_win_num; id++, win++) {
+               win = &win_map->dram_windows[id];
+               set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win);
+       }
+
+       return 0;
+}
+
+/*
+ * init_io_addr_dec
+ *
+ * This function initializes io address decoder windows by
+ * cpu dram window mapping information
+ *
+ * @input: N/A
+ *     - dram_wins_map: cpu dram windows mapping
+ *     - io_dec_config: io address decoder windows configuration
+ *     - io_unit_num: io address decoder unit number
+ * @output: N/A
+ *
+ * @return:  0 on success and others on failure
+ */
+int init_io_addr_dec(struct dram_win_map *dram_wins_map,
+                    struct dec_win_config *io_dec_config, uint32_t io_unit_num)
+{
+       int32_t index;
+       struct dec_win_config *io_dec_win;
+       int32_t ret;
+
+       INFO("Initializing IO address decode windows\n");
+
+       if (io_dec_config == NULL || io_unit_num == 0) {
+               ERROR("No IO address decoder windows configurations!\n");
+               return -1;
+       }
+
+       if (io_unit_num > IO_UNIT_NUM_MAX) {
+               ERROR("IO address decoder windows number %d is over max %d\n",
+                     io_unit_num, IO_UNIT_NUM_MAX);
+               return -1;
+       }
+
+       if (dram_wins_map == NULL) {
+               ERROR("No cpu dram decoder windows map!\n");
+               return -1;
+       }
+
+       for (index = 0; index < dram_wins_map->dram_win_num; index++)
+               INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n",
+                    index, dram_wins_map->dram_windows[index].base_addr,
+                    dram_wins_map->dram_windows[index].win_size);
+
+       /* Set address decode window for each IO */
+       for (index = 0; index < io_unit_num; index++) {
+               io_dec_win = io_dec_config + index;
+               ret = set_io_addr_dec(dram_wins_map, io_dec_win);
+               if (ret) {
+                       ERROR("Failed to set IO address decode\n");
+                       return -1;
+               }
+               INFO("Set IO decode window successfully, base(0x%x)",
+                    io_dec_win->dec_reg_base);
+               INFO(" win_attr(%x) max_dram_win(%d) max_remap(%d)",
+                    io_dec_win->win_attr, io_dec_win->max_dram_win,
+                    io_dec_win->max_remap);
+               INFO(" win_offset(%d)\n", io_dec_win->win_offset);
+       }
+
+       return 0;
+}
diff --git a/plat/marvell/a3700/common/marvell_plat_config.c b/plat/marvell/a3700/common/marvell_plat_config.c
new file mode 100644 (file)
index 0000000..85a4201
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <bl_common.h>
+#include <io_addr_dec.h>
+#include <mvebu_def.h>
+
+struct dec_win_config io_dec_win_conf[] = {
+       /* dec_reg_base  win_attr  max_dram_win  max_remap  win_offset */
+       {0xc000,         0x3d,     2,       0,        0x08}, /* USB */
+       {0xc100,         0x3d,     3,       0,        0x10}, /* USB3 */
+       {0xc200,         0x3d,     2,       0,        0x10}, /* DMA */
+       {0xc300,         0x3d,     2,       0,        0x10}, /* NETA0 */
+       {0xc400,         0x3d,     2,       0,        0x10}, /* NETA1 */
+       {0xc500,         0x3d,     2,       0,        0x10}, /* PCIe */
+       {0xc800,         0x3d,     3,       0,        0x10}, /* SATA */
+       {0xca00,         0x3d,     3,       0,        0x08}, /* SD */
+       {0xcb00,         0x3d,     3,       0,        0x10}, /* eMMC */
+       {0xce00,         0x3d,     2,       0,        0x08}, /* EIP97 */
+};
+
+int marvell_get_io_dec_win_conf(struct dec_win_config **win, uint32_t *size)
+{
+       *win = io_dec_win_conf;
+       *size = sizeof(io_dec_win_conf)/sizeof(struct dec_win_config);
+
+       return 0;
+}
+
diff --git a/plat/marvell/a3700/common/plat_pm.c b/plat/marvell/a3700/common/plat_pm.c
new file mode 100644 (file)
index 0000000..5cebc92
--- /dev/null
@@ -0,0 +1,815 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a3700_pm.h>
+#include <arch_helpers.h>
+#include <armada_common.h>
+#include <debug.h>
+#include <dram_win.h>
+#include <io_addr_dec.h>
+#include <mmio.h>
+#include <mvebu.h>
+#include <mvebu_def.h>
+#include <marvell_plat_priv.h>
+#include <platform.h>
+#include <plat_marvell.h>
+#include <psci.h>
+#ifdef USE_CCI
+#include <cci.h>
+#endif
+
+/* Warm reset register */
+#define MVEBU_WARM_RESET_REG           (MVEBU_NB_REGS_BASE + 0x840)
+#define MVEBU_WARM_RESET_MAGIC         0x1D1E
+
+/* North Bridge GPIO1 SEL register */
+#define MVEBU_NB_GPIO1_SEL_REG         (MVEBU_NB_REGS_BASE + 0x830)
+ #define MVEBU_NB_GPIO1_UART1_SEL      BIT(19)
+ #define MVEBU_NB_GPIO1_GPIO_25_26_EN  BIT(17)
+ #define MVEBU_NB_GPIO1_GPIO_19_EN     BIT(14)
+ #define MVEBU_NB_GPIO1_GPIO_18_EN     BIT(13)
+
+/* CPU 1 reset register */
+#define MVEBU_CPU_1_RESET_VECTOR       (MVEBU_REGS_BASE + 0x14044)
+#define MVEBU_CPU_1_RESET_REG          (MVEBU_REGS_BASE + 0xD00C)
+#define MVEBU_CPU_1_RESET_BIT          31
+
+/* IRQ register */
+#define MVEBU_NB_IRQ_STATUS_1_REG              (MVEBU_NB_SB_IRQ_REG_BASE)
+#define MVEBU_NB_IRQ_STATUS_2_REG              (MVEBU_NB_SB_IRQ_REG_BASE + \
+                                               0x10)
+#define MVEBU_NB_IRQ_MASK_2_REG                        (MVEBU_NB_SB_IRQ_REG_BASE + \
+                                               0x18)
+#define MVEBU_SB_IRQ_STATUS_1_REG              (MVEBU_NB_SB_IRQ_REG_BASE + \
+                                               0x40)
+#define MVEBU_SB_IRQ_STATUS_2_REG              (MVEBU_NB_SB_IRQ_REG_BASE + \
+                                               0x50)
+#define MVEBU_NB_GPIO_IRQ_MASK_1_REG           (MVEBU_NB_SB_IRQ_REG_BASE + \
+                                               0xC8)
+#define MVEBU_NB_GPIO_IRQ_MASK_2_REG           (MVEBU_NB_SB_IRQ_REG_BASE + \
+                                               0xD8)
+#define MVEBU_SB_GPIO_IRQ_MASK_REG             (MVEBU_NB_SB_IRQ_REG_BASE + \
+                                               0xE8)
+#define MVEBU_NB_GPIO_IRQ_EN_LOW_REG           (MVEBU_NB_GPIO_IRQ_REG_BASE)
+#define MVEBU_NB_GPIO_IRQ_EN_HIGH_REG          (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+                                               0x04)
+#define MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG       (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+                                               0x10)
+#define MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG      (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+                                               0x14)
+#define MVEBU_NB_GPIO_IRQ_WK_LOW_REG           (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+                                               0x18)
+#define MVEBU_NB_GPIO_IRQ_WK_HIGH_REG          (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+                                               0x1C)
+#define MVEBU_SB_GPIO_IRQ_EN_REG               (MVEBU_SB_GPIO_IRQ_REG_BASE)
+#define MVEBU_SB_GPIO_IRQ_STATUS_REG           (MVEBU_SB_GPIO_IRQ_REG_BASE + \
+                                               0x10)
+#define MVEBU_SB_GPIO_IRQ_WK_REG               (MVEBU_SB_GPIO_IRQ_REG_BASE + \
+                                               0x18)
+
+/* PMU registers */
+#define MVEBU_PM_NB_PWR_CTRL_REG       (MVEBU_PMSU_REG_BASE)
+ #define MVEBU_PM_PWR_DN_CNT_SEL       BIT(28)
+ #define MVEBU_PM_SB_PWR_DWN           BIT(4)
+ #define MVEBU_PM_INTERFACE_IDLE       BIT(0)
+#define MVEBU_PM_NB_CPU_PWR_CTRL_REG   (MVEBU_PMSU_REG_BASE + 0x4)
+ #define MVEBU_PM_L2_FLUSH_EN          BIT(22)
+#define MVEBU_PM_NB_PWR_OPTION_REG     (MVEBU_PMSU_REG_BASE + 0x8)
+ #define MVEBU_PM_DDR_SR_EN            BIT(29)
+ #define MVEBU_PM_DDR_CLK_DIS_EN       BIT(28)
+ #define MVEBU_PM_WARM_RESET_EN                BIT(27)
+ #define MVEBU_PM_DDRPHY_PWRDWN_EN     BIT(23)
+ #define MVEBU_PM_DDRPHY_PAD_PWRDWN_EN BIT(22)
+ #define MVEBU_PM_OSC_OFF_EN           BIT(21)
+ #define MVEBU_PM_TBG_OFF_EN           BIT(20)
+ #define MVEBU_PM_CPU_VDDV_OFF_EN      BIT(19)
+ #define MVEBU_PM_AVS_DISABLE_MODE     BIT(14)
+ #define MVEBU_PM_AVS_VDD2_MODE                BIT(13)
+ #define MVEBU_PM_AVS_HOLD_MODE                BIT(12)
+ #define MVEBU_PM_L2_SRAM_LKG_PD_EN    BIT(8)
+ #define MVEBU_PM_EIP_SRAM_LKG_PD_EN   BIT(7)
+ #define MVEBU_PM_DDRMC_SRAM_LKG_PD_EN BIT(6)
+ #define MVEBU_PM_MCI_SRAM_LKG_PD_EN   BIT(5)
+ #define MVEBU_PM_MMC_SRAM_LKG_PD_EN   BIT(4)
+ #define MVEBU_PM_SATA_SRAM_LKG_PD_EN  BIT(3)
+ #define MVEBU_PM_DMA_SRAM_LKG_PD_EN   BIT(2)
+ #define MVEBU_PM_SEC_SRAM_LKG_PD_EN   BIT(1)
+ #define MVEBU_PM_CPU_SRAM_LKG_PD_EN   BIT(0)
+ #define MVEBU_PM_NB_SRAM_LKG_PD_EN    (MVEBU_PM_L2_SRAM_LKG_PD_EN |\
+       MVEBU_PM_EIP_SRAM_LKG_PD_EN | MVEBU_PM_DDRMC_SRAM_LKG_PD_EN |\
+       MVEBU_PM_MCI_SRAM_LKG_PD_EN | MVEBU_PM_MMC_SRAM_LKG_PD_EN |\
+       MVEBU_PM_SATA_SRAM_LKG_PD_EN | MVEBU_PM_DMA_SRAM_LKG_PD_EN |\
+       MVEBU_PM_SEC_SRAM_LKG_PD_EN | MVEBU_PM_CPU_SRAM_LKG_PD_EN)
+#define MVEBU_PM_NB_PWR_DEBUG_REG      (MVEBU_PMSU_REG_BASE + 0xC)
+ #define MVEBU_PM_NB_FORCE_CLK_ON      BIT(30)
+ #define MVEBU_PM_IGNORE_CM3_SLEEP     BIT(21)
+ #define MVEBU_PM_IGNORE_CM3_DEEP      BIT(20)
+#define MVEBU_PM_NB_WAKE_UP_EN_REG     (MVEBU_PMSU_REG_BASE + 0x2C)
+ #define MVEBU_PM_SB_WKP_NB_EN         BIT(31)
+ #define MVEBU_PM_NB_GPIO_WKP_EN       BIT(27)
+ #define MVEBU_PM_SOC_TIMER_WKP_EN     BIT(26)
+ #define MVEBU_PM_UART_WKP_EN          BIT(25)
+ #define MVEBU_PM_UART2_WKP_EN         BIT(19)
+ #define MVEBU_PM_CPU_TIMER_WKP_EN     BIT(17)
+ #define MVEBU_PM_NB_WKP_EN            BIT(16)
+ #define MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN BIT(13)
+ #define MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN BIT(12)
+#define MVEBU_PM_CPU_0_PWR_CTRL_REG    (MVEBU_PMSU_REG_BASE + 0x34)
+#define MVEBU_PM_CPU_1_PWR_CTRL_REG    (MVEBU_PMSU_REG_BASE + 0x38)
+ #define MVEBU_PM_CORE_SOC_PD          BIT(2)
+ #define MVEBU_PM_CORE_PROC_PD         BIT(1)
+ #define MVEBU_PM_CORE_PD              BIT(0)
+#define MVEBU_PM_CORE_1_RETURN_ADDR_REG        (MVEBU_PMSU_REG_BASE + 0x44)
+#define MVEBU_PM_CPU_VDD_OFF_INFO_1_REG        (MVEBU_PMSU_REG_BASE + 0x48)
+#define MVEBU_PM_CPU_VDD_OFF_INFO_2_REG        (MVEBU_PMSU_REG_BASE + 0x4C)
+ #define MVEBU_PM_LOW_POWER_STATE      BIT(0)
+#define MVEBU_PM_CPU_WAKE_UP_CONF_REG  (MVEBU_PMSU_REG_BASE + 0x54)
+ #define MVEBU_PM_CORE1_WAKEUP         BIT(13)
+ #define MVEBU_PM_CORE0_WAKEUP         BIT(12)
+#define MVEBU_PM_WAIT_DDR_RDY_VALUE    (0x15)
+#define MVEBU_PM_SB_CPU_PWR_CTRL_REG   (MVEBU_SB_WAKEUP_REG_BASE)
+  #define MVEBU_PM_SB_PM_START         BIT(0)
+#define MVEBU_PM_SB_PWR_OPTION_REG     (MVEBU_SB_WAKEUP_REG_BASE + 0x4)
+  #define MVEBU_PM_SDIO_PHY_PDWN_EN    BIT(17)
+  #define MVEBU_PM_SB_VDDV_OFF_EN      BIT(16)
+  #define MVEBU_PM_EBM_SRAM_LKG_PD_EN          BIT(11)
+  #define MVEBU_PM_PCIE_SRAM_LKG_PD_EN         BIT(10)
+  #define MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN      BIT(9)
+  #define MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN      BIT(8)
+  #define MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN     BIT(7)
+  #define MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN      BIT(6)
+  #define MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN      BIT(5)
+  #define MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN     BIT(4)
+  #define MVEBU_PM_SDIO_SRAM_LKG_PD_EN         BIT(3)
+  #define MVEBU_PM_USB2_SRAM_LKG_PD_EN         BIT(2)
+  #define MVEBU_PM_USB3_H_SRAM_LKG_PD_EN       BIT(1)
+  #define MVEBU_PM_SB_SRAM_LKG_PD_EN   (MVEBU_PM_EBM_SRAM_LKG_PD_EN |\
+       MVEBU_PM_PCIE_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN |\
+       MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN |\
+       MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN | MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN |\
+       MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN | MVEBU_PM_SDIO_SRAM_LKG_PD_EN |\
+       MVEBU_PM_USB2_SRAM_LKG_PD_EN | MVEBU_PM_USB3_H_SRAM_LKG_PD_EN)
+#define MVEBU_PM_SB_WK_EN_REG          (MVEBU_SB_WAKEUP_REG_BASE + 0x10)
+  #define MVEBU_PM_SB_GPIO_WKP_EN      BIT(24)
+  #define MVEBU_PM_SB_WKP_EN           BIT(20)
+
+/* DRAM registers */
+#define MVEBU_DRAM_STATS_CH0_REG       (MVEBU_DRAM_REG_BASE + 0x4)
+ #define MVEBU_DRAM_WCP_EMPTY          BIT(19)
+#define MVEBU_DRAM_CMD_0_REG           (MVEBU_DRAM_REG_BASE + 0x20)
+ #define MVEBU_DRAM_CH0_CMD0           BIT(28)
+ #define MVEBU_DRAM_CS_CMD0            BIT(24)
+ #define MVEBU_DRAM_WCB_DRAIN_REQ      BIT(1)
+#define MVEBU_DRAM_PWR_CTRL_REG                (MVEBU_DRAM_REG_BASE + 0x54)
+ #define MVEBU_DRAM_PHY_CLK_GATING_EN  BIT(1)
+ #define MVEBU_DRAM_PHY_AUTO_AC_OFF_EN BIT(0)
+
+/* AVS registers */
+#define MVEBU_AVS_CTRL_2_REG           (MVEBU_AVS_REG_BASE + 0x8)
+ #define MVEBU_LOW_VDD_MODE_EN         BIT(6)
+
+/* Clock registers */
+#define MVEBU_NB_CLOCK_SEL_REG         (MVEBU_NB_REGS_BASE + 0x10)
+ #define MVEBU_A53_CPU_CLK_SEL         BIT(15)
+
+/* North Bridge Step-Down Registers */
+#define MVEBU_NB_STEP_DOWN_INT_EN_REG  MVEBU_NB_STEP_DOWN_REG_BASE
+ #define MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK       BIT(8)
+
+#define MVEBU_NB_GPIO_18       18
+#define MVEBU_NB_GPIO_19       19
+#define MVEBU_NB_GPIO_25       25
+#define MVEBU_NB_GPIO_26       26
+
+typedef int (*wake_up_src_func)(union pm_wake_up_src_data *);
+
+struct wake_up_src_func_map {
+       enum pm_wake_up_src_type type;
+       wake_up_src_func func;
+};
+
+void marvell_psci_arch_init(int die_index)
+{
+}
+
+static void a3700_pm_ack_irq(void)
+{
+       uint32_t reg;
+
+       reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_1_REG);
+       if (reg)
+               mmio_write_32(MVEBU_NB_IRQ_STATUS_1_REG, reg);
+
+       reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_2_REG);
+       if (reg)
+               mmio_write_32(MVEBU_NB_IRQ_STATUS_2_REG, reg);
+
+       reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_1_REG);
+       if (reg)
+               mmio_write_32(MVEBU_SB_IRQ_STATUS_1_REG, reg);
+
+       reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_2_REG);
+       if (reg)
+               mmio_write_32(MVEBU_SB_IRQ_STATUS_2_REG, reg);
+
+       reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG);
+       if (reg)
+               mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG, reg);
+
+       reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG);
+       if (reg)
+               mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG, reg);
+
+       reg = mmio_read_32(MVEBU_SB_GPIO_IRQ_STATUS_REG);
+       if (reg)
+               mmio_write_32(MVEBU_SB_GPIO_IRQ_STATUS_REG, reg);
+}
+
+/*****************************************************************************
+ * A3700 handler called to check the validity of the power state
+ * parameter.
+ *****************************************************************************
+ */
+int a3700_validate_power_state(unsigned int power_state,
+                              psci_power_state_t *req_state)
+{
+       ERROR("%s needs to be implemented\n", __func__);
+       panic();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a CPU is about to enter standby.
+ *****************************************************************************
+ */
+void a3700_cpu_standby(plat_local_state_t cpu_state)
+{
+       ERROR("%s needs to be implemented\n", __func__);
+       panic();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ *****************************************************************************
+ */
+int a3700_pwr_domain_on(u_register_t mpidr)
+{
+       /* Set barrier */
+       dsbsy();
+
+       /* Set the cpu start address to BL1 entry point */
+       mmio_write_32(MVEBU_CPU_1_RESET_VECTOR,
+                     PLAT_MARVELL_CPU_ENTRY_ADDR >> 2);
+
+       /* Get the cpu out of reset */
+       mmio_clrbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT));
+       mmio_setbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT));
+
+       return 0;
+}
+
+/*****************************************************************************
+ * A3700 handler called to validate the entry point.
+ *****************************************************************************
+ */
+int a3700_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+       return PSCI_E_SUCCESS;
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ *****************************************************************************
+ */
+void 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
+        */
+       a3700_pm_ack_irq();
+}
+
+static void a3700_set_gen_pwr_off_option(void)
+{
+       /* Enable L2 flush -> processor state-machine option */
+       mmio_setbits_32(MVEBU_PM_NB_CPU_PWR_CTRL_REG, MVEBU_PM_L2_FLUSH_EN);
+
+       /*
+        * North bridge cannot be VDD off (always ON).
+        * The NB state machine support low power mode by its state machine.
+        * This bit MUST be set for north bridge power down, e.g.,
+        * OSC input cutoff(NOT TEST), SRAM power down, PMIC, etc.
+        * It is not related to CPU VDD OFF!!
+        */
+       mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_CPU_VDDV_OFF_EN);
+
+       /*
+        * MUST: Switch CPU/AXI clock to OSC
+        * NB state machine clock is always connected to OSC (slow clock).
+        * But Core0/1/processor state machine's clock are connected to AXI
+        *  clock. Now, AXI clock takes the TBG as clock source.
+        * If using AXI clock, Core0/1/processor state machine may much faster
+        * than NB state machine. It will cause problem in this case if cores
+        * are released before north bridge gets ready.
+        */
+       mmio_clrbits_32(MVEBU_NB_CLOCK_SEL_REG, MVEBU_A53_CPU_CLK_SEL);
+
+       /*
+        * These register bits will trigger north bridge
+        * power-down state machine regardless CM3 status.
+        */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_SLEEP);
+       mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_DEEP);
+
+       /*
+        * SRAM => controlled by north bridge state machine.
+        * Core VDD OFF is not related to CPU SRAM power down.
+        */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_NB_SRAM_LKG_PD_EN);
+
+       /*
+        * Idle AXI interface in order to get L2_WFI
+        * L2 WFI is only asserted after CORE-0 and CORE-1 WFI asserted.
+        * (only both core-0/1in WFI, L2 WFI will be issued by CORE.)
+        * Once L2 WFI asserted, this bit is used for signalling assertion
+        * to AXI IO masters.
+        */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_INTERFACE_IDLE);
+
+       /* Enable core0 and core1 VDD_OFF */
+       mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PD);
+       mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PD);
+
+       /* Enable North bridge power down -
+        * Both Cores MUST enable this bit to power down north bridge!
+        */
+       mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD);
+       mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD);
+
+       /* CA53 (processor domain) power down */
+       mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD);
+       mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD);
+}
+
+static void a3700_en_ddr_self_refresh(void)
+{
+       /*
+        * Both count is 16 bits and configurable. By default, osc stb cnt
+        * is 0xFFF for lower 12 bits.
+        * Thus, powerdown count is smaller than osc count.
+        * This count is used for exiting DDR SR mode on wakeup event.
+        * The powerdown count also has impact on the following
+        * state changes: idle -> count-down -> ... (power-down, vdd off, etc)
+        * Here, make stable counter shorter
+        * Use power down count value instead of osc_stb_cnt to speed up
+        * DDR self refresh exit
+        */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_PWR_DN_CNT_SEL);
+
+       /*
+        * Enable DDR SR mode => controlled by north bridge state machine
+        * Therefore, we must powerdown north bridge to trigger the DDR SR
+        * mode switching.
+        */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_SR_EN);
+       /* Disable DDR clock, otherwise DDR will not enter into SR mode. */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_CLK_DIS_EN);
+       /* Power down DDR PHY (PAD) */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDRPHY_PWRDWN_EN);
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG,
+                       MVEBU_PM_DDRPHY_PAD_PWRDWN_EN);
+
+       /* Set wait time for DDR ready in ROM code */
+       mmio_write_32(MVEBU_PM_CPU_VDD_OFF_INFO_1_REG,
+                     MVEBU_PM_WAIT_DDR_RDY_VALUE);
+
+       /* DDR flush write buffer - mandatory */
+       mmio_write_32(MVEBU_DRAM_CMD_0_REG, MVEBU_DRAM_CH0_CMD0 |
+                     MVEBU_DRAM_CS_CMD0 | MVEBU_DRAM_WCB_DRAIN_REQ);
+       while ((mmio_read_32(MVEBU_DRAM_STATS_CH0_REG) &
+                            MVEBU_DRAM_WCP_EMPTY) != MVEBU_DRAM_WCP_EMPTY)
+               ;
+
+       /* Trigger PHY reset after ddr out of self refresh =>
+        * supply reset pulse for DDR phy after wake up
+        */
+       mmio_setbits_32(MVEBU_DRAM_PWR_CTRL_REG, MVEBU_DRAM_PHY_CLK_GATING_EN |
+                                                MVEBU_DRAM_PHY_AUTO_AC_OFF_EN);
+}
+
+static void a3700_pwr_dn_avs(void)
+{
+       /*
+        * AVS power down - controlled by north bridge statemachine
+        * Enable AVS power down by clear the AVS disable bit.
+        */
+       mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_DISABLE_MODE);
+       /*
+        * Should set BIT[12:13] to powerdown AVS.
+        * 1. Enable AVS VDD2 mode
+        * 2. After power down AVS, we must hold AVS output voltage.
+        * 3. We can choose the lower VDD for AVS power down.
+        */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_VDD2_MODE);
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_HOLD_MODE);
+
+       /* Enable low VDD mode, AVS will set CPU to lowest core VDD 747mV */
+       mmio_setbits_32(MVEBU_AVS_CTRL_2_REG, MVEBU_LOW_VDD_MODE_EN);
+}
+
+static void a3700_pwr_dn_tbg(void)
+{
+       /* Power down TBG */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_TBG_OFF_EN);
+}
+
+static void a3700_pwr_dn_sb(void)
+{
+       /* Enable south bridge power down option */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_SB_PWR_DWN);
+
+       /* Enable SDIO_PHY_PWRDWN */
+       mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SDIO_PHY_PDWN_EN);
+
+       /* Enable SRAM LRM on SB */
+       mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_SRAM_LKG_PD_EN);
+
+       /* Enable SB Power Off */
+       mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_VDDV_OFF_EN);
+
+       /* Kick off South Bridge Power Off */
+       mmio_setbits_32(MVEBU_PM_SB_CPU_PWR_CTRL_REG, MVEBU_PM_SB_PM_START);
+}
+
+static void a3700_set_pwr_off_option(void)
+{
+       /* Set general power off option */
+       a3700_set_gen_pwr_off_option();
+
+       /* Enable DDR self refresh in low power mode */
+       a3700_en_ddr_self_refresh();
+
+       /* Power down AVS */
+       a3700_pwr_dn_avs();
+
+       /* Power down TBG */
+       a3700_pwr_dn_tbg();
+
+       /* Power down south bridge, pay attention south bridge setting
+        * should be done before
+        */
+       a3700_pwr_dn_sb();
+}
+
+static void a3700_set_wake_up_option(void)
+{
+       /*
+        * Enable the wakeup event for NB SOC => north-bridge
+        * state-machine enablement on wake-up event
+        */
+       mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_WKP_EN);
+
+        /* Enable both core0 and core1 wakeup on demand */
+       mmio_setbits_32(MVEBU_PM_CPU_WAKE_UP_CONF_REG,
+                       MVEBU_PM_CORE1_WAKEUP | MVEBU_PM_CORE0_WAKEUP);
+
+       /* Enable warm reset in low power mode */
+       mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_WARM_RESET_EN);
+}
+
+static void a3700_pm_en_nb_gpio(uint32_t gpio)
+{
+       /* For GPIO1 interrupt -- North bridge only */
+       if (gpio >= 32) {
+               /* GPIO int mask */
+               mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_2_REG, BIT(gpio - 32));
+
+               /* NB_CPU_WAKE-up ENABLE GPIO int */
+               mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_HIGH_REG, BIT(gpio - 32));
+       } else {
+               /* GPIO int mask */
+               mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_1_REG, BIT(gpio));
+
+               /* NB_CPU_WAKE-up ENABLE GPIO int */
+               mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_LOW_REG, BIT(gpio));
+       }
+
+       mmio_setbits_32(MVEBU_NB_STEP_DOWN_INT_EN_REG,
+                       MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK);
+
+       /* Enable using GPIO as wakeup event
+        * (actually not only for north bridge)
+        */
+       mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_GPIO_WKP_EN |
+               MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN |
+               MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN);
+}
+
+static void a3700_pm_en_sb_gpio(uint32_t gpio)
+{
+       /* Enable using GPIO as wakeup event */
+       mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_SB_WKP_NB_EN |
+               MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN |
+               MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN);
+
+       /* SB GPIO Wake UP | South Bridge Wake Up Enable */
+       mmio_setbits_32(MVEBU_PM_SB_WK_EN_REG, MVEBU_PM_SB_GPIO_WKP_EN |
+                       MVEBU_PM_SB_GPIO_WKP_EN);
+
+       /* GPIO int mask */
+       mmio_clrbits_32(MVEBU_SB_GPIO_IRQ_MASK_REG, BIT(gpio));
+
+       /* NB_CPU_WAKE-up ENABLE GPIO int */
+       mmio_setbits_32(MVEBU_SB_GPIO_IRQ_EN_REG, BIT(gpio));
+}
+
+int a3700_pm_src_gpio(union pm_wake_up_src_data *src_data)
+{
+       if (src_data->gpio_data.bank_num == 0)
+               /* North Bridge GPIO */
+               a3700_pm_en_nb_gpio(src_data->gpio_data.gpio_num);
+       else
+               a3700_pm_en_sb_gpio(src_data->gpio_data.gpio_num);
+       return 0;
+}
+
+int a3700_pm_src_uart1(union pm_wake_up_src_data *src_data)
+{
+       /* Clear Uart1 select */
+       mmio_clrbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_UART1_SEL);
+       /* set pin 19 gpio usage*/
+       mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_19_EN);
+       /* Enable gpio wake-up*/
+       a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_19);
+       /* set pin 18 gpio usage*/
+       mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_18_EN);
+       /* Enable gpio wake-up*/
+       a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_18);
+
+       return 0;
+}
+
+int a3700_pm_src_uart0(union pm_wake_up_src_data *src_data)
+{
+       /* set pin 25/26 gpio usage*/
+       mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_25_26_EN);
+       /* Enable gpio wake-up*/
+       a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_25);
+       /* Enable gpio wake-up*/
+       a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_26);
+
+       return 0;
+}
+
+struct wake_up_src_func_map src_func_table[WAKE_UP_SRC_MAX] = {
+       {WAKE_UP_SRC_GPIO, a3700_pm_src_gpio},
+       {WAKE_UP_SRC_UART1, a3700_pm_src_uart1},
+       {WAKE_UP_SRC_UART0, a3700_pm_src_uart0},
+       /* FOLLOWING SRC NOT SUPPORTED YET */
+       {WAKE_UP_SRC_TIMER, NULL}
+};
+
+static wake_up_src_func a3700_get_wake_up_src_func(
+                                                 enum pm_wake_up_src_type type)
+{
+       uint32_t loop;
+
+       for (loop = 0; loop < WAKE_UP_SRC_MAX; loop++) {
+               if (src_func_table[loop].type == type)
+                       return src_func_table[loop].func;
+       }
+       return NULL;
+}
+
+static void a3700_set_wake_up_source(void)
+{
+       struct pm_wake_up_src_config *wake_up_src;
+       uint32_t loop;
+       wake_up_src_func src_func = NULL;
+
+       wake_up_src = mv_wake_up_src_config_get();
+       for (loop = 0; loop < wake_up_src->wake_up_src_num; loop++) {
+               src_func = a3700_get_wake_up_src_func(
+                          wake_up_src->wake_up_src[loop].wake_up_src_type);
+               if (src_func)
+                       src_func(
+                               &(wake_up_src->wake_up_src[loop].wake_up_data));
+       }
+}
+
+static void a3700_pm_save_lp_flag(void)
+{
+       /* Save the flag for enter the low power mode */
+       mmio_setbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG,
+                       MVEBU_PM_LOW_POWER_STATE);
+}
+
+static void a3700_pm_clear_lp_flag(void)
+{
+       /* Clear the flag for enter the low power mode */
+       mmio_clrbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG,
+                       MVEBU_PM_LOW_POWER_STATE);
+}
+
+static uint32_t a3700_pm_get_lp_flag(void)
+{
+       /* Get the flag for enter the low power mode */
+       return mmio_read_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG) &
+                           MVEBU_PM_LOW_POWER_STATE;
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ *****************************************************************************
+ */
+void a3700_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+       /* Prevent interrupts from spuriously waking up this cpu */
+       plat_marvell_gic_cpuif_disable();
+
+       /* Save IRQ states */
+       plat_marvell_gic_irq_save();
+
+       /* Set wake up options */
+       a3700_set_wake_up_option();
+
+       /* Set wake up sources */
+       a3700_set_wake_up_source();
+
+       /* SoC can not be powered down with pending IRQ,
+        * acknowledge all the pending IRQ
+        */
+       a3700_pm_ack_irq();
+
+       /* Set power off options */
+       a3700_set_pwr_off_option();
+
+       /* Save the flag for enter the low power mode */
+       a3700_pm_save_lp_flag();
+
+       isb();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ *****************************************************************************
+ */
+void a3700_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+       /* arch specific configuration */
+       marvell_psci_arch_init(0);
+
+       /* Per-CPU interrupt initialization */
+       plat_marvell_gic_pcpu_init();
+       plat_marvell_gic_cpuif_enable();
+
+       /* Restore the per-cpu IRQ state */
+       if (a3700_pm_get_lp_flag())
+               plat_marvell_gic_irq_pcpu_restore();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ *****************************************************************************
+ */
+void a3700_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+       struct dec_win_config *io_dec_map;
+       uint32_t dec_win_num;
+       struct dram_win_map dram_wins_map;
+
+       /* arch specific configuration */
+       marvell_psci_arch_init(0);
+
+       /* Interrupt initialization */
+       plat_marvell_gic_init();
+
+       /* Restore IRQ states */
+       plat_marvell_gic_irq_restore();
+
+       /*
+        * Initialize CCI for this cluster after resume from suspend state.
+        * No need for locks as no other CPU is active.
+        */
+       plat_marvell_interconnect_init();
+       /*
+        * Enable CCI coherency for the primary CPU's cluster.
+        * Platform specific PSCI code will enable coherency for other
+        * clusters.
+        */
+       plat_marvell_interconnect_enter_coherency();
+
+       /* CPU address decoder windows initialization. */
+       cpu_wins_init();
+
+       /* fetch CPU-DRAM window mapping information by reading
+        * CPU-DRAM decode windows (only the enabled ones)
+        */
+       dram_win_map_build(&dram_wins_map);
+
+       /* Get IO address decoder windows */
+       if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) {
+               printf("No IO address decoder windows configurations found!\n");
+               return;
+       }
+
+       /* IO address decoder init */
+       if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) {
+               printf("IO address decoder windows initialization failed!\n");
+               return;
+       }
+
+       /* Clear low power mode flag */
+       a3700_pm_clear_lp_flag();
+}
+
+/*****************************************************************************
+ * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND
+ * call to get the `power_state` parameter. This allows the platform to encode
+ * the appropriate State-ID field within the `power_state` parameter which can
+ * be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
+ *****************************************************************************
+ */
+void a3700_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+       /* lower affinities use PLAT_MAX_OFF_STATE */
+       for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+               req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+/*****************************************************************************
+ * A3700 handlers to shutdown/reboot the system
+ *****************************************************************************
+ */
+static void __dead2 a3700_system_off(void)
+{
+       ERROR("%s needs to be implemented\n", __func__);
+       panic();
+}
+
+/*****************************************************************************
+ * A3700 handlers to reset the system
+ *****************************************************************************
+ */
+static void __dead2 a3700_system_reset(void)
+{
+       /* Clean the mailbox magic number to let it as act like cold boot */
+       mmio_write_32(PLAT_MARVELL_MAILBOX_BASE, 0x0);
+
+       dsbsy();
+
+       /* Flush data cache if the mail box shared RAM is cached */
+#if PLAT_MARVELL_SHARED_RAM_CACHED
+       flush_dcache_range((uintptr_t)PLAT_MARVELL_MAILBOX_BASE,
+                          2 * sizeof(uint64_t));
+#endif
+
+       /* Trigger the warm reset */
+       mmio_write_32(MVEBU_WARM_RESET_REG, MVEBU_WARM_RESET_MAGIC);
+
+       /* Shouldn't get to this point */
+       panic();
+}
+
+/*****************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ *****************************************************************************
+ */
+const plat_psci_ops_t plat_arm_psci_pm_ops = {
+       .cpu_standby = a3700_cpu_standby,
+       .pwr_domain_on = a3700_pwr_domain_on,
+       .pwr_domain_off = a3700_pwr_domain_off,
+       .pwr_domain_suspend = a3700_pwr_domain_suspend,
+       .pwr_domain_on_finish = a3700_pwr_domain_on_finish,
+       .pwr_domain_suspend_finish = a3700_pwr_domain_suspend_finish,
+       .get_sys_suspend_power_state = a3700_get_sys_suspend_power_state,
+       .system_off = a3700_system_off,
+       .system_reset = a3700_system_reset,
+       .validate_power_state = a3700_validate_power_state,
+       .validate_ns_entrypoint = a3700_validate_ns_entrypoint
+};
diff --git a/plat/marvell/common/marvell_gicv3.c b/plat/marvell/common/marvell_gicv3.c
new file mode 100644 (file)
index 0000000..7cfefaf
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <debug.h>
+#include <gicv3.h>
+#include <interrupt_props.h>
+#include <marvell_def.h>
+#include <plat_marvell.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ ******************************************************************************
+ */
+#pragma weak plat_marvell_gic_driver_init
+#pragma weak plat_marvell_gic_init
+#pragma weak plat_marvell_gic_cpuif_enable
+#pragma weak plat_marvell_gic_cpuif_disable
+#pragma weak plat_marvell_gic_pcpu_init
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t marvell_interrupt_props[] = {
+       PLAT_MARVELL_G1S_IRQ_PROPS(INTR_GROUP1S),
+       PLAT_MARVELL_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * We save and restore the GICv3 context on system suspend. Allocate the
+ * data in the designated EL3 Secure carve-out memory
+ */
+static gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram");
+static gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram");
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ *   - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ *   - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int marvell_gicv3_mpidr_hash(u_register_t mpidr)
+{
+       mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+       return plat_marvell_calc_core_pos(mpidr);
+}
+
+const gicv3_driver_data_t marvell_gic_data = {
+       .gicd_base = PLAT_MARVELL_GICD_BASE,
+       .gicr_base = PLAT_MARVELL_GICR_BASE,
+       .interrupt_props = marvell_interrupt_props,
+       .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props),
+       .rdistif_num = PLATFORM_CORE_COUNT,
+       .rdistif_base_addrs = rdistif_base_addrs,
+       .mpidr_to_core_pos = marvell_gicv3_mpidr_hash
+};
+
+void plat_marvell_gic_driver_init(void)
+{
+       /*
+        * The GICv3 driver is initialized in EL3 and does not need
+        * to be initialized again in SEL1. This is because the S-EL1
+        * can use GIC system registers to manage interrupts and does
+        * not need GIC interface base addresses to be configured.
+        */
+#if IMAGE_BL31
+       gicv3_driver_init(&marvell_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * Marvell common helper to initialize the GIC. Only invoked by BL31
+ ******************************************************************************
+ */
+void plat_marvell_gic_init(void)
+{
+       /* Initialize GIC-600 Multi Chip feature,
+        * only if the maximum number of north bridges
+        * is more than 1 - otherwise no need for multi
+        * chip feature initialization
+        */
+#if (PLAT_MARVELL_NORTHB_COUNT > 1)
+       if (gic600_multi_chip_init())
+               ERROR("GIC-600 Multi Chip initialization failed\n");
+#endif
+       gicv3_distif_init();
+       gicv3_rdistif_init(plat_my_core_pos());
+       gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to enable the GIC CPU interface
+ ******************************************************************************
+ */
+void plat_marvell_gic_cpuif_enable(void)
+{
+       gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to disable the GIC CPU interface
+ ******************************************************************************
+ */
+void plat_marvell_gic_cpuif_disable(void)
+{
+       gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to init. the per-cpu redistributor interface in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_pcpu_init(void)
+{
+       gicv3_rdistif_init(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to save SPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_save(void)
+{
+
+       /*
+        * If an ITS is available, save its context before
+        * the Redistributor using:
+        * gicv3_its_save_disable(gits_base, &its_ctx[i])
+        * Additionally, an implementation-defined sequence may
+        * be required to save the whole ITS state.
+        */
+
+       /*
+        * Save the GIC Redistributors and ITS contexts before the
+        * Distributor context. As we only handle SYSTEM SUSPEND API,
+        * we only need to save the context of the CPU that is issuing
+        * the SYSTEM SUSPEND call, i.e. the current CPU.
+        */
+       gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+
+       /* Save the GIC Distributor context */
+       gicv3_distif_save(&dist_ctx);
+
+       /*
+        * From here, all the components of the GIC can be safely powered down
+        * as long as there is an alternate way to handle wakeup interrupt
+        * sources.
+        */
+}
+
+/******************************************************************************
+ * Marvell common helper to restore SPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_restore(void)
+{
+       /* Restore the GIC Distributor context */
+       gicv3_distif_init_restore(&dist_ctx);
+
+       /*
+        * Restore the GIC Redistributor and ITS contexts after the
+        * Distributor context. As we only handle SYSTEM SUSPEND API,
+        * we only need to restore the context of the CPU that issued
+        * the SYSTEM SUSPEND call.
+        */
+       gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+
+       /*
+        * If an ITS is available, restore its context after
+        * the Redistributor using:
+        * gicv3_its_restore(gits_base, &its_ctx[i])
+        * An implementation-defined sequence may be required to
+        * restore the whole ITS state. The ITS must also be
+        * re-enabled after this sequence has been executed.
+        */
+}
+
+/******************************************************************************
+ * Marvell common helper to save per-cpu PPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_pcpu_save(void)
+{
+       gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+}
+
+/******************************************************************************
+ * Marvell common helper to restore per-cpu PPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_pcpu_restore(void)
+{
+       gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+}
index 2a2da3b93b45862f3de09ab75a6162515e138fe8..d8be0dd174fdfbfd70f30a3e4549a50efa26fad1 100644 (file)
@@ -49,6 +49,6 @@ mrvl_clean:
 
 ${DOIMAGETOOL}: mrvl_clean
        @$(DOIMAGE_LIBS_CHECK)
-       ${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH} WTMI_IMG=$(WTMI_IMG)
+       ${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH} VERSION=$(SUBVERSION) WTMI_IMG=$(WTMI_IMG)