summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Porotchkin <kostap@marvell.com>2017-03-20 16:41:14 +0200
committerKonstantin Porotchkin <kostap@marvell.com>2017-04-02 17:36:42 +0300
commit4712fa35c1b04a421c8722501a37eb481b379e1f (patch)
tree5b49c98eb72f279cde2e1303277ff1a67d8215ea
parent38560c8f99c907d44abbcc5eee1b82feab256a67 (diff)
drivers: Add drivers for Marvell A7K and A8K platforms
Add Marvell drivers for A7K and A8K SoC families Change-Id: I7fb530e543e4f64782f41f8a058b6aabd82af9e8 Signed-off-by: Haim Boot <hayim@marvell.com> Signed-off-by: Konstantin Porotchkin <kostap@marvell.com> Reviewed-on: http://vgitil04.il.marvell.com:8080/37916
-rw-r--r--docs/marvell/misc/mvebu-amb.txt45
-rw-r--r--docs/marvell/misc/mvebu-ccu.txt38
-rw-r--r--docs/marvell/misc/mvebu-iob.txt56
-rw-r--r--docs/marvell/misc/mvebu-rfu.txt48
-rw-r--r--drivers/marvell/amb_adec.c166
-rw-r--r--drivers/marvell/cache_llc.c99
-rw-r--r--drivers/marvell/ccu.c266
-rw-r--r--drivers/marvell/comphy.h390
-rw-r--r--drivers/marvell/dw-pcie-ep.c178
-rw-r--r--drivers/marvell/i2c/a8k_i2c.c563
-rw-r--r--drivers/marvell/icu.c143
-rw-r--r--drivers/marvell/iob.c206
-rw-r--r--drivers/marvell/mci.c617
-rw-r--r--drivers/marvell/mochi/apn806_setup.c216
-rw-r--r--drivers/marvell/mochi/cp110_setup.c400
-rw-r--r--drivers/marvell/pci_ep.h59
-rw-r--r--drivers/marvell/pcie-comphy-cp110.c418
-rw-r--r--drivers/marvell/rfu.c197
-rw-r--r--include/drivers/marvell/a8k_i2c.h61
-rw-r--r--include/drivers/marvell/amb_adec.h68
-rw-r--r--include/drivers/marvell/cache_llc.h33
-rw-r--r--include/drivers/marvell/ccu.h63
-rw-r--r--include/drivers/marvell/i2c.h46
-rw-r--r--include/drivers/marvell/icu.h60
-rw-r--r--include/drivers/marvell/iob.h61
-rw-r--r--include/drivers/marvell/mci.h260
-rw-r--r--include/drivers/marvell/mochi/apn806_setup.h60
-rw-r--r--include/drivers/marvell/mochi/cp110_setup.h59
-rw-r--r--include/drivers/marvell/rfu.h64
29 files changed, 4940 insertions, 0 deletions
diff --git a/docs/marvell/misc/mvebu-amb.txt b/docs/marvell/misc/mvebu-amb.txt
new file mode 100644
index 00000000..40a74674
--- /dev/null
+++ b/docs/marvell/misc/mvebu-amb.txt
@@ -0,0 +1,45 @@
+AMB - AXI MBUS address decoding
+-------------------------------
+
+- The Runit offers a second level of address windows lookup. It is used to map transaction towards
+the CD BootROM, SPI0, SPI1 and Device bus (NOR).
+- The Runit contains eight configurable windows. Each window defines a contiguous,
+address space and the properties associated with that address space.
+
+Unit Bank ATTR
+Device-Bus DEV_BOOT_CS 0x2F
+ DEV_CS0 0x3E
+ DEV_CS1 0x3D
+ DEV_CS2 0x3B
+ DEV_CS3 0x37
+SPI-0 SPI_A_CS0 0x1E
+ SPI_A_CS1 0x5E
+ SPI_A_CS2 0x9E
+ SPI_A_CS3 0xDE
+ SPI_A_CS4 0x1F
+ SPI_A_CS5 0x5F
+ SPI_A_CS6 0x9F
+ SPI_A_CS7 0xDF
+SPI1 SPI_B_CS0 0x1A
+ SPI_B_CS1 0x5A
+ SPI_B_CS2 0x9A
+ SPI_B_CS3 0xDA
+BOOT_ROM BOOT_ROM 0x1D
+UART UART 0x01
+
+Mandatory functions:
+ - marvell_get_amb_reg_offs
+ returns the base address of the AXI-MBUS(AMB) unit
+ - marvell_get_amb_memory_map
+ returns the AMB windows configuration and the number of windows
+
+Mandatory structures:
+ amb_memory_map - Array that include the configuration of the windows
+ every window/entry is a struct which has 2 parameters:
+ - base address of the window
+ - Attribute of the window
+
+Examples:
+ struct amb_win amb_memory_map[] = {
+ {0xf900, AMB_DEV_CS0_ID},
+ };
diff --git a/docs/marvell/misc/mvebu-ccu.txt b/docs/marvell/misc/mvebu-ccu.txt
new file mode 100644
index 00000000..c8b5df5d
--- /dev/null
+++ b/docs/marvell/misc/mvebu-ccu.txt
@@ -0,0 +1,38 @@
+Marvell CCU address decoding bindings
+=====================================
+
+The CCU node includes a description of the address decoding configuration.
+
+Mandatory functions:
+ - marvell_get_ccu_reg_offs
+ returns the base address of the CCU unit
+ - marvell_get_ccu_max_win
+ returns the number of the max mbus windows
+ - marvell_get_ccu_memory_map
+ return the CCU windows configuration and the number of windows
+
+Mandatory structures:
+ ccu_memory_map - Array that includes the configuration of the windows
+ every window/entry is a struct which has 5 parameters:
+ - High base address of the window
+ - Low base address of the window
+ - High size of the window
+ - Low size of the window
+ - Target-ID of the window
+
+Note: if the base address is more than 32 bits, it should be divided into high and low.
+ The same goes for the Size field. If it is larger than 32 bits, it is divided into
+ high and low.
+ Base example:
+ base address: 0x10f0000000 should be divided into:
+ base address high: 0x10
+ base address low: 0xf0000000
+ Size example:
+ size: 0x1E00F00000 should be divided into:
+ size high: 0x1E
+ size low: 0x00F00000
+
+Example:
+ struct ccu_win ccu_memory_map[] = {
+ {0x0, 0xf2000000, 0x0, 0xe000000, IO_0_TID}, /* IO window */
+ };
diff --git a/docs/marvell/misc/mvebu-iob.txt b/docs/marvell/misc/mvebu-iob.txt
new file mode 100644
index 00000000..5bd81c62
--- /dev/null
+++ b/docs/marvell/misc/mvebu-iob.txt
@@ -0,0 +1,56 @@
+Marvell IOB address decoding bindings
+=====================================
+
+The IOB includes a description of the address decoding configuration.
+
+IOB supports up to n (in CP110 n=24) windows for external memory transaction.
+When a transaction passes through the IOB, its address is compared to each of
+the enabled windows. If there is a hit and it passes the security checks, it is
+advanced to the target port.
+
+Mandatory functions:
+ - marvell_get_iob_reg_offs
+ returns the base address of the IOB unit
+ - marvell_get_iob_max_win
+ returns the number of the max IOB windows
+ - marvell_get_iob_memory_map
+ returns the IOB windows configuration and the number of windows
+
+Mandatory structures:
+ iob_memory_map - Array that include the configuration of the windows
+ every window/entry is a struct which has 5 parameters:
+ - High base address of the window
+ - Low base address of the window
+ - High size of the window
+ - Low size of the window
+ - Target-ID of the window
+
+Target ID options:
+ - 0x0 = Internal configuration space
+ - 0x1 = MCI0
+ - 0x2 = PEX1_X1
+ - 0x3 = PEX2_X1
+ - 0x4 = PEX0_X4
+ - 0x5 = NAND flash
+ - 0x6 = RUNIT (NOR/SPI/BootRoom)
+ - 0x7 = MCI1
+
+Note: if the base address is more than 32 bits, it divided into high and low.
+ The same goes for the Size field, if it more that 32 bits, it divided into
+ high and low.
+ Base example:
+ base address: 0x10f0000000 should divided into:
+ base address high: 0x10
+ base address low: 0xf0000000
+ Size example:
+ size: 0x1E00F00000 should divided into:
+ size high: 0x1E
+ size low: 0x00F00000
+
+Example:
+ struct iob_win iob_memory_map[] = {
+ {0x0, 0xf7000000, 0x0, 0x1000000, PEX1_TID}, /* PEX1_X1 window */
+ {0x0, 0xf8000000, 0x0, 0x1000000, PEX2_TID}, /* PEX2_X1 window */
+ {0x0, 0xf6000000, 0x0, 0x1000000, PEX0_TID}, /* PEX0_X4 window */
+ {0x0, 0xf9000000, 0x0, 0x1000000, NAND_TID} /* NAND window */
+ };
diff --git a/docs/marvell/misc/mvebu-rfu.txt b/docs/marvell/misc/mvebu-rfu.txt
new file mode 100644
index 00000000..e525c960
--- /dev/null
+++ b/docs/marvell/misc/mvebu-rfu.txt
@@ -0,0 +1,48 @@
+Marvell RFU address decoding bindings
+=====================================
+
+The RFU includes a description of the address decoding configuration.
+
+Transactions that are decoded by CCU windows as IO peripheral, have an additional
+layer of decoding. This additional address decoding layer defines one of the
+following targets:
+ 0x0 = BootRom
+ 0x1 = STM (Serial Trace Macro-cell, a programmer's port into trace stream)
+ 0x2 = SPI direct access
+ 0x3 = PCIe registers
+ 0x4 = MCI Port
+ 0x5 = PCIe port
+
+Mandatory functions:
+ - marvell_get_rfu_reg_offs
+ returns the base address of the RFU unit
+ - marvell_get_rfu_memory_map
+ returns the RFU windows configuration and the number of windows
+
+Mandatory structures:
+ rfu_memory_map - Array that include the configuration of the windows
+ every window/entry is a struct which has 5 parameters:
+ - High base address of the window
+ - Low base address of the window
+ - High size of the window
+ - Low size of the window
+ - Target-ID of the window
+
+Note: if the base address is more than 32 bits, it divided into high and low.
+ The same goes for the Size field, if it more that 32 bits, is divided into
+ high and low.
+ Base example:
+ base address: 0x10f0000000 should divided into:
+ base address high: 0x10
+ base address low: 0xf0000000
+ Size example:
+ size: 0x1E00F00000 should divided into:
+ size high: 0x1E
+ size low: 0x00F00000
+
+Example:
+ struct rfu_win rfu_memory_map[] = {
+ {0x0, 0xfe000000, 0x0, 0x1f00000, PCIE_PORT_TID}, /* PCIe window 31Mb for PCIe port*/
+ {0x0, 0xffe00000, 0x0, 0x100000, PCIE_REGS_TID}, /* PCI-REG window 64Kb for PCIe-reg*/
+ {0x0, 0xf6000000, 0x0, 0x100000, MCIPHY_TID}, /* MCI window 1Mb for PHY-reg*/
+ };
diff --git a/drivers/marvell/amb_adec.c b/drivers/marvell/amb_adec.c
new file mode 100644
index 00000000..2a827a6f
--- /dev/null
+++ b/drivers/marvell/amb_adec.c
@@ -0,0 +1,166 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <debug.h>
+#include <mmio.h>
+#include <mvebu.h>
+#include <plat_config.h>
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+#define DEBUG_ADDR_MAP
+#endif
+
+/* common defines */
+#define WIN_ENABLE_BIT (0x1)
+
+#define AMB_WIN_CR_OFFSET(win) (amb_base + 0x0 + (0x8 * win))
+#define AMB_ATTR_OFFSET 8
+#define AMB_ATTR_MASK 0xFF
+#define AMB_SIZE_OFFSET 16
+#define AMB_SIZE_MASK 0xFF
+
+#define AMB_WIN_BASE_OFFSET(win) (amb_base + 0x4 + (0x8 * win))
+#define AMB_BASE_OFFSET 16
+
+#define AMB_WIN_ALIGNMENT_64K (0x10000)
+#define AMB_WIN_ALIGNMENT_1M (0x100000)
+
+uintptr_t amb_base;
+
+static void amb_check_win(struct amb_win *win, uint32_t win_num)
+{
+ uint32_t alignment_value = AMB_WIN_ALIGNMENT_1M;
+ uint32_t base_addr = win->base_addr << AMB_BASE_OFFSET;
+
+ /* for AMB The base is always 1M aligned */
+ /* check if address is aligned to 1M */
+
+ if (IS_NOT_ALIGN(base_addr, alignment_value)) {
+ win->base_addr = ALIGN_UP(base_addr, alignment_value);
+ printf("Warning: Window %d: base address unaligned to 0x%x\n", win_num, alignment_value);
+ printf("Align up the base address to 0x%x\n", win->base_addr);
+ }
+
+ /* size parameter validity check */
+ if (!IS_POWER_OF_2(win->win_size)) {
+ printf("Warning: Window %d: window size is not power of 2 (0x%x)\n", win_num, win->win_size);
+ win->win_size = ROUND_UP_TO_POW_OF_2(win->win_size);
+ printf("Rounding size to 0x%x\n", win->win_size);
+ }
+}
+
+static void amb_enable_win(struct amb_win *win, uint32_t win_num)
+{
+ uint32_t ctrl, base, size;
+
+ size = (win->win_size / AMB_WIN_ALIGNMENT_64K) - 1; /* size is 64KB granularity.
+ * The number of 1s specifies the size of the
+ * window in 64 KB granularity. 0 is 64KB */
+ ctrl = (size << AMB_SIZE_OFFSET) | (win->attribute << AMB_ATTR_OFFSET);
+ base = win->base_addr << AMB_BASE_OFFSET;
+
+ mmio_write_32(AMB_WIN_BASE_OFFSET(win_num), base);
+ mmio_write_32(AMB_WIN_CR_OFFSET(win_num), ctrl);
+
+ /* enable window after configuring window size (and attributes) */
+ ctrl |= WIN_ENABLE_BIT;
+ mmio_write_32(AMB_WIN_CR_OFFSET(win_num), ctrl);
+}
+#ifdef DEBUG_ADDR_MAP
+static void dump_amb_adec(void)
+{
+ uint32_t ctrl, base, win_id, attr;
+ uint32_t size, size_count;
+
+ /* Dump all AMB windows */
+ printf("bank attribute base size\n");
+ printf("--------------------------------------------\n");
+ for (win_id = 0; win_id < AMB_MAX_WIN_ID; win_id++) {
+ ctrl = mmio_read_32(AMB_WIN_CR_OFFSET(win_id));
+ if (ctrl & WIN_ENABLE_BIT) {
+ base = mmio_read_32(AMB_WIN_BASE_OFFSET(win_id));
+ attr = (ctrl >> AMB_ATTR_OFFSET) & AMB_ATTR_MASK;
+ size_count = (ctrl >> AMB_SIZE_OFFSET) & AMB_SIZE_MASK;
+ size = (size_count + 1) * AMB_WIN_ALIGNMENT_64K;
+ printf("amb 0x%04x 0x%08x 0x%08x\n", attr, base, size);
+ }
+ }
+
+ return;
+}
+#endif
+
+int init_amb_adec(int cp_index)
+{
+ struct amb_win *win;
+ uint32_t win_id, win_reg;
+ uint32_t win_count;
+
+ INFO("Initializing AXI to MBus Bridge Address decoding\n");
+
+ /* Get the base address of the AMB address decoding */
+ amb_base = marvell_get_amb_reg_offs(cp_index);
+
+ /* Get the array of the windows and its size */
+ marvell_get_amb_memory_map(&win, &win_count);
+ if (win_count <= 0)
+ INFO("no windows configurations found\n");
+
+ if (win_count > AMB_MAX_WIN_ID) {
+ INFO("number of windows is bigger than %d\n", AMB_MAX_WIN_ID);
+ return 0;
+ }
+
+ /* disable all AMB windows */
+ for (win_id = 0; win_id < AMB_MAX_WIN_ID; win_id++) {
+ win_reg = mmio_read_32(AMB_WIN_CR_OFFSET(win_id));
+ win_reg &= ~WIN_ENABLE_BIT;
+ mmio_write_32(AMB_WIN_CR_OFFSET(win_id), win_reg);
+ }
+
+ /* enable relevant windows */
+ for (win_id = 0; win_id < win_count; win_id++, win++) {
+ amb_check_win(win, win_id);
+ amb_enable_win(win, win_id);
+ }
+
+#ifdef DEBUG_ADDR_MAP
+ dump_amb_adec();
+#endif
+
+ INFO("Done AXI to MBus Bridge Address decoding Initializing\n");
+
+ return 0;
+}
diff --git a/drivers/marvell/cache_llc.c b/drivers/marvell/cache_llc.c
new file mode 100644
index 00000000..cb5eed3c
--- /dev/null
+++ b/drivers/marvell/cache_llc.c
@@ -0,0 +1,99 @@
+/*
+ * ***************************************************************************
+ * Copyright (C) 2015 Marvell International Ltd.
+ * ***************************************************************************
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 2 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * ***************************************************************************
+ */
+
+#include <assert.h>
+#include <mmio.h>
+#include <plat_def.h>
+
+#define LLC_CTRL 0x100
+#define LLC_CACHE_SYNC 0x700
+#define L2X0_INV_WAY 0x77C
+#define L2X0_CLEAN_WAY 0x7BC
+#define L2X0_CLEAN_INV_WAY 0x7FC
+
+#define LLC_CTRL_EN 1
+#define LLC_EXCLUSIVE_EN 0x100
+#define LLC_WAY_MASK 0xFFFFFFFF
+
+void llc_cache_sync(void)
+{
+ mmio_write_32(MVEBU_LLC_BASE + LLC_CACHE_SYNC, 0);
+ /* Atumic write no need to wait */
+}
+
+void llc_flush_all(void)
+{
+ mmio_write_32(MVEBU_LLC_BASE + L2X0_CLEAN_INV_WAY, LLC_WAY_MASK);
+ llc_cache_sync();
+}
+
+void llc_clean_all(void)
+{
+ mmio_write_32(MVEBU_LLC_BASE + L2X0_CLEAN_WAY, LLC_WAY_MASK);
+ llc_cache_sync();
+}
+
+void llc_inv_all(void)
+{
+ mmio_write_32(MVEBU_LLC_BASE + L2X0_INV_WAY, LLC_WAY_MASK);
+ llc_cache_sync();
+}
+
+void llc_disable(void)
+{
+ llc_flush_all();
+ mmio_write_32(MVEBU_LLC_BASE + LLC_CTRL, 0);
+ __asm__ volatile("dsb st");
+}
+
+void llc_enable(int excl_mode)
+{
+ uint32_t val;
+
+ __asm__ volatile("dsb sy");
+ llc_inv_all();
+ __asm__ volatile("dsb sy");
+
+ val = LLC_CTRL_EN;
+ if (excl_mode)
+ val |= LLC_EXCLUSIVE_EN;
+
+ mmio_write_32(MVEBU_LLC_BASE + LLC_CTRL, val);
+ __asm__ volatile("dsb sy");
+}
+
+int llc_is_exclusive(void)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(MVEBU_LLC_BASE + LLC_CTRL);
+
+ if ((reg & (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) == (LLC_CTRL_EN | LLC_EXCLUSIVE_EN))
+ return 1;
+ return 0;
+}
+
+void llc_save(void)
+{
+ /* TBD */
+}
+
+void llc_resume(void)
+{
+ /* TBD */
+}
diff --git a/drivers/marvell/ccu.c b/drivers/marvell/ccu.c
new file mode 100644
index 00000000..4edfeb8b
--- /dev/null
+++ b/drivers/marvell/ccu.c
@@ -0,0 +1,266 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <debug.h>
+#include <mmio.h>
+#include <mvebu.h>
+#include <ccu.h>
+#include <plat_config.h>
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+#define DEBUG_ADDR_MAP
+#endif
+
+/* common defines */
+#define WIN_ENABLE_BIT (0x1)
+/* Physical address of the base of the window = {AddrLow[19:0],20’h0} */
+#define ADDRESS_SHIFT (20 - 4)
+#define ADDRESS_MASK (0xFFFFFFF0)
+#define CCU_WIN_ALIGNMENT (0x100000)
+
+/* AP registers */
+#define CCU_MAX_WIN_NUM (8)
+#define CCU_WIN_CR_OFFSET(win) (ccu_info->ccu_base + 0x0 + (0x10 * win))
+#define CCU_TARGET_ID_OFFSET (8)
+#define CCU_TARGET_ID_MASK (0x7F)
+
+#define CCU_WIN_SCR_OFFSET(win) (ccu_info->ccu_base + 0x4 + (0x10 * win))
+#define CCU_WIN_ENA_WRITE_SECURE (0x1)
+#define CCU_WIN_ENA_READ_SECURE (0x2)
+
+#define CCU_WIN_ALR_OFFSET(win) (ccu_info->ccu_base + 0x8 + (0x10 * win))
+#define CCU_WIN_AHR_OFFSET(win) (ccu_info->ccu_base + 0xC + (0x10 * win))
+
+#define CCU_WIN_GCR_OFFSET (ccu_info->ccu_base + 0xD0)
+#define CCU_GCR_TARGET_OFFSET (8)
+#define CCU_GCR_TARGET_MASK (0xF)
+
+
+struct ccu_configuration {
+ uintptr_t ccu_base;
+ uint32_t max_win;
+};
+
+struct ccu_configuration ccu_config;
+struct ccu_configuration *ccu_info = &ccu_config;
+
+#ifdef DEBUG_ADDR_MAP
+struct ccu_target_name_map {
+ enum ccu_target_ids trgt_id;
+ char name[10];
+};
+
+struct ccu_target_name_map ccu_target_name_table[] = {
+ {IO_0_TID, "IO-0 "},
+ {DRAM_0_TID, "DRAM-0 "},
+ {IO_1_TID, "IO-1 "},
+ {CFG_REG_TID, "CFG-REG"},
+ {RAR_TID, "RAR "},
+ {SRAM_TID, "SRAM "},
+ {DRAM_1_TID, "DRAM-1 "},
+ {INVALID_TID, "INVALID"},
+};
+
+static char *ccu_target_name_get(enum ccu_target_ids trgt_id)
+{
+ int i;
+
+ for (i = 0; i < CCU_MAX_TID; i++)
+ if (ccu_target_name_table[i].trgt_id == trgt_id)
+ return ccu_target_name_table[i].name;
+ return ccu_target_name_get(INVALID_TID);
+}
+
+static void dump_ccu(void)
+{
+ uint32_t win_id, win_cr, alr, ahr;
+ uint8_t target_id;
+ uint64_t start, end;
+
+ /* Dump all AP windows */
+ printf("bank id target start end\n");
+ printf("----------------------------------------------------\n");
+ for (win_id = 0; win_id < ccu_info->max_win; win_id++) {
+ win_cr = mmio_read_32(CCU_WIN_CR_OFFSET(win_id));
+ printf("Win %d: 0x%lx: 0x%x\n", win_id, CCU_WIN_CR_OFFSET(win_id), win_cr);
+ if (win_cr & WIN_ENABLE_BIT) {
+ printf("\tWin %d: Enabled\n", win_id);
+ target_id = (win_cr >> CCU_TARGET_ID_OFFSET) & CCU_TARGET_ID_MASK;
+ alr = mmio_read_32(CCU_WIN_ALR_OFFSET(win_id));
+ ahr = mmio_read_32(CCU_WIN_AHR_OFFSET(win_id));
+ start = ((uint64_t)alr << ADDRESS_SHIFT);
+ end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT);
+ printf("ccu %02x %s 0x%016lx 0x%016lx\n"
+ , win_id, ccu_target_name_get(target_id), start, end);
+ }
+ }
+ win_cr = mmio_read_32(CCU_WIN_GCR_OFFSET);
+ target_id = (win_cr >> CCU_GCR_TARGET_OFFSET) & CCU_GCR_TARGET_MASK;
+ printf("ccu GCR %s - all other transactions\n", ccu_target_name_get(target_id));
+
+ return;
+}
+#endif
+
+static void ccu_win_check(struct ccu_win *win, uint32_t win_num)
+{
+ uint64_t start_addr, win_size;
+
+ /* check if address is aligned to 1M */
+ start_addr = ((uint64_t)win->base_addr_high << 32) + win->base_addr_low;
+ if (IS_NOT_ALIGN(start_addr, CCU_WIN_ALIGNMENT)) {
+ start_addr = ALIGN_UP(start_addr, CCU_WIN_ALIGNMENT);
+ ERROR("Window %d: base address unaligned to 0x%x\n", win_num, CCU_WIN_ALIGNMENT);
+ printf("Align up the base address to 0x%lx\n", start_addr);
+ win->base_addr_high = (uint32_t)(start_addr >> 32);
+ win->base_addr_low = (uint32_t)(start_addr);
+ }
+
+ /* size parameter validity check */
+ win_size = ((uint64_t)win->win_size_high << 32) + win->win_size_low;
+ if (IS_NOT_ALIGN(win_size, CCU_WIN_ALIGNMENT)) {
+ win_size = ALIGN_UP(win_size, CCU_WIN_ALIGNMENT);
+ ERROR("Window %d: window size unaligned to 0x%x\n", win_num, CCU_WIN_ALIGNMENT);
+ printf("Aligning size to 0x%lx\n", win_size);
+ win->win_size_high = (uint32_t)(win_size >> 32);
+ win->win_size_low = (uint32_t)(win_size);
+ }
+}
+
+static void ccu_enable_win(struct ccu_win *win, uint32_t win_id)
+{
+ uint32_t ccu_win_reg;
+ uint32_t alr, ahr;
+ uint64_t start_addr, end_addr;
+
+ start_addr = ((uint64_t)win->base_addr_high << 32) + win->base_addr_low;
+ end_addr = (start_addr + (((uint64_t)win->win_size_high << 32) + win->win_size_low) - 1);
+ alr = (uint32_t)((start_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
+ ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
+
+ mmio_write_32(CCU_WIN_ALR_OFFSET(win_id), alr);
+ mmio_write_32(CCU_WIN_AHR_OFFSET(win_id), ahr);
+
+ ccu_win_reg = WIN_ENABLE_BIT;
+ ccu_win_reg |= (win->target_id & CCU_TARGET_ID_MASK) << CCU_TARGET_ID_OFFSET;
+ mmio_write_32(CCU_WIN_CR_OFFSET(win_id), ccu_win_reg);
+}
+
+static int skip_ccu_window(uint32_t win_reg)
+{
+ uint8_t target_id;
+
+ /* avoid overriding internal register and SRAM windows
+ At SPL stage BootROM open the SRAM window and close it
+ at the end of the SPL stage */
+ if (win_reg & WIN_ENABLE_BIT) {
+ target_id = (win_reg >> CCU_TARGET_ID_OFFSET) & CCU_TARGET_ID_MASK;
+ if (((target_id) == SRAM_TID) || ((target_id) == CFG_REG_TID))
+ return 1;
+ }
+
+ return 0;
+}
+
+int init_ccu(void)
+{
+ struct ccu_win *win;
+ uint32_t win_id, win_reg;
+ uint32_t win_count, array_id;
+
+ INFO("Initializing CCU Address decoding\n");
+
+ /* Get the base address of the address decoding CCU */
+ ccu_info->ccu_base = marvell_get_ccu_reg_offs();
+
+ /* Get the maximum number of CCU windows supported */
+ ccu_info->max_win = marvell_get_ccu_max_win();
+ if ((ccu_info->max_win == 0) || (ccu_info->max_win > CCU_MAX_WIN_NUM)) {
+ ccu_info->max_win = CCU_MAX_WIN_NUM;
+ ERROR("failed reading max windows number, set window max size to %d\n", ccu_info->max_win);
+ }
+
+ /* Get the array of the windows and fill the map data */
+ marvell_get_ccu_memory_map(&win, &win_count);
+ if (win_count <= 0) {
+ INFO("no windows configurations found\n");
+ return 0;
+ }
+
+ /* Set the default target ID to DRAM 0 */
+ win_reg = (DRAM_0_TID & CCU_GCR_TARGET_MASK) << CCU_GCR_TARGET_OFFSET;
+ mmio_write_32(CCU_WIN_GCR_OFFSET, win_reg);
+
+ /* disable AP windows */
+ for (win_id = 0; win_id < ccu_info->max_win; win_id++) {
+ win_reg = mmio_read_32(CCU_WIN_CR_OFFSET(win_id));
+ if (skip_ccu_window(win_reg))
+ continue;
+
+ win_reg &= ~WIN_ENABLE_BIT;
+ mmio_write_32(CCU_WIN_CR_OFFSET(win_id), win_reg);
+
+ /* enable write secure (and clear read secure) */
+ win_reg = CCU_WIN_ENA_WRITE_SECURE;
+ mmio_write_32(CCU_WIN_SCR_OFFSET(win_id), win_reg);
+ }
+
+ for (win_id = 0, array_id = 0;
+ ((win_id < ccu_info->max_win) && (array_id < win_count)); win_id++) {
+ /* win_id is the index of the current ccu window
+ array_id is the index of the current FDT window entry */
+
+ win_reg = mmio_read_32(CCU_WIN_CR_OFFSET(win_id));
+ if (skip_ccu_window(win_reg))
+ continue;
+
+ ccu_win_check(win, win_id);
+ ccu_enable_win(win, win_id);
+
+ win++;
+ array_id++;
+ }
+
+ if (array_id != win_count)
+ ERROR("Set only %d CCU windows. expected %d", array_id, win_count);
+
+#ifdef DEBUG_ADDR_MAP
+ dump_ccu();
+#endif
+
+ INFO("Done CCU Address decoding Initializing\n");
+
+ return 0;
+}
diff --git a/drivers/marvell/comphy.h b/drivers/marvell/comphy.h
new file mode 100644
index 00000000..67807c49
--- /dev/null
+++ b/drivers/marvell/comphy.h
@@ -0,0 +1,390 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _COMPHY_H_
+#define _COMPHY_H_
+
+/* COMPHY registers */
+#define COMMON_PHY_CFG1_REG 0x0
+#define COMMON_PHY_CFG1_PWR_UP_OFFSET 1
+#define COMMON_PHY_CFG1_PWR_UP_MASK (0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET)
+#define COMMON_PHY_CFG1_PIPE_SELECT_OFFSET 2
+#define COMMON_PHY_CFG1_PIPE_SELECT_MASK (0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET)
+#define COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET 13
+#define COMMON_PHY_CFG1_PWR_ON_RESET_MASK (0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET)
+#define COMMON_PHY_CFG1_CORE_RSTN_OFFSET 14
+#define COMMON_PHY_CFG1_CORE_RSTN_MASK (0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET)
+#define COMMON_PHY_PHY_MODE_OFFSET 15
+#define COMMON_PHY_PHY_MODE_MASK (0x1 << COMMON_PHY_PHY_MODE_OFFSET)
+
+#define COMMON_PHY_CFG6_REG 0x14
+#define COMMON_PHY_CFG6_IF_40_SEL_OFFSET 18
+#define COMMON_PHY_CFG6_IF_40_SEL_MASK (0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET)
+
+#define COMMON_SELECTOR_PHY_OFFSET 0x140
+#define COMMON_SELECTOR_PIPE_OFFSET 0x144
+
+#define COMMON_PHY_SD_CTRL1 0x148
+#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET 0
+#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK 0xFFFF
+#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET 24
+#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET)
+#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET 25
+#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET)
+#define COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET 26
+#define COMMON_PHY_SD_CTRL1_RXAUI1_MASK (0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET)
+#define COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET 27
+#define COMMON_PHY_SD_CTRL1_RXAUI0_MASK (0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET)
+
+#define DFX_DEV_GEN_CTRL12 0x80
+#define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET 7
+#define DFX_DEV_GEN_PCIE_CLK_SRC_MASK (0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET)
+
+#define MAX_LANE_OPTIONS 10
+#define MAX_UTMI_PHY_COUNT 3
+
+
+/* SerDes IP register */
+#define SD_EXTERNAL_CONFIG0_REG 0
+#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET 1
+#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK (1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET 3
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET 7
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET 11
+#define SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK (1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET 12
+#define SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK (1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET 14
+#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK (1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET)
+#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET 15
+#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK (0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET)
+
+#define SD_EXTERNAL_CONFIG1_REG 0x4
+#define SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET 3
+#define SD_EXTERNAL_CONFIG1_RESET_IN_MASK (0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET 4
+#define SD_EXTERNAL_CONFIG1_RX_INIT_MASK (0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET 5
+#define SD_EXTERNAL_CONFIG1_RESET_CORE_MASK (0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET 6
+#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK (0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET)
+
+#define SD_EXTERNAL_CONFIG2_REG 0x8
+#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET 4
+#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK (0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET)
+
+#define SD_EXTERNAL_STATUS0_REG 0x18
+#define SD_EXTERNAL_STATUS0_PLL_TX_OFFSET 2
+#define SD_EXTERNAL_STATUS0_PLL_TX_MASK (0x1 << SD_EXTERNAL_STATUS0_PLL_TX_OFFSET)
+#define SD_EXTERNAL_STATUS0_PLL_RX_OFFSET 3
+#define SD_EXTERNAL_STATUS0_PLL_RX_MASK (0x1 << SD_EXTERNAL_STATUS0_PLL_RX_OFFSET)
+#define SD_EXTERNAL_STATUS0_RX_INIT_OFFSET 4
+#define SD_EXTERNAL_STATUS0_RX_INIT_MASK (0x1 << SD_EXTERNAL_STATUS0_RX_INIT_OFFSET)
+#define SD_EXTERNAL_STATUS0_RF_RESET_IN_OFFSET 6
+#define SD_EXTERNAL_STATUS0_RF_RESET_IN_MASK (0x1 << SD_EXTERNAL_STATUS0_RF_RESET_IN_OFFSET)
+
+/* HPIPE register */
+#define HPIPE_PWR_PLL_REG 0x4
+#define HPIPE_PWR_PLL_REF_FREQ_OFFSET 0
+#define HPIPE_PWR_PLL_REF_FREQ_MASK (0x1f << HPIPE_PWR_PLL_REF_FREQ_OFFSET)
+#define HPIPE_PWR_PLL_PHY_MODE_OFFSET 5
+#define HPIPE_PWR_PLL_PHY_MODE_MASK (0x7 << HPIPE_PWR_PLL_PHY_MODE_OFFSET)
+
+#define HPIPE_KVCO_CALIB_CTRL_REG 0x8
+#define HPIPE_KVCO_CALIB_CTRL_MAX_PLL_OFFSET 12
+#define HPIPE_KVCO_CALIB_CTRL_MAX_PLL_MASK (0x1 << HPIPE_KVCO_CALIB_CTRL_MAX_PLL_OFFSET)
+
+#define HPIPE_CAL_REG1_REG 0xc
+#define HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET 10
+#define HPIPE_CAL_REG_1_EXT_TXIMP_MASK (0x1f << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET)
+#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET 15
+#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK (0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET)
+
+#define HPIPE_SQUELCH_FFE_SETTING_REG 0x018
+
+#define HPIPE_DFE_REG0 0x01C
+#define HPIPE_DFE_RES_FORCE_OFFSET 15
+#define HPIPE_DFE_RES_FORCE_MASK (0x1 << HPIPE_DFE_RES_FORCE_OFFSET)
+
+#define HPIPE_DFE_F3_F5_REG 0x028
+#define HPIPE_DFE_F3_F5_DFE_EN_OFFSET 14
+#define HPIPE_DFE_F3_F5_DFE_EN_MASK (0x1 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET)
+#define HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET 15
+#define HPIPE_DFE_F3_F5_DFE_CTRL_MASK (0x1 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET)
+
+#define HPIPE_G1_SET_0_REG 0x034
+#define HPIPE_G1_SET_0_G1_TX_AMP_OFFSET 1
+#define HPIPE_G1_SET_0_G1_TX_AMP_MASK (0x1f << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET)
+#define HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET 7
+#define HPIPE_G1_SET_0_G1_TX_EMPH1_MASK (0xf << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET)
+
+#define HPIPE_G1_SET_1_REG 0x038
+#define HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET 0
+#define HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET)
+#define HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET 3
+#define HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET)
+#define HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET 10
+#define HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK (0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET)
+
+#define HPIPE_G2_SETTINGS_1_REG 0x040
+
+#define HPIPE_G3_SETTINGS_1_REG 0x048
+#define HPIPE_G3_RX_SELMUPI_OFFSET 0
+#define HPIPE_G3_RX_SELMUPI_MASK (0x7 << HPIPE_G3_RX_SELMUPI_OFFSET)
+#define HPIPE_G3_RX_SELMUPF_OFFSET 3
+#define HPIPE_G3_RX_SELMUPF_MASK (0x7 << HPIPE_G3_RX_SELMUPF_OFFSET)
+#define HPIPE_G3_SETTING_BIT_OFFSET 13
+#define HPIPE_G3_SETTING_BIT_MASK (0x1 << HPIPE_G3_SETTING_BIT_OFFSET)
+
+#define HPIPE_LOOPBACK_REG 0x08c
+#define HPIPE_LOOPBACK_SEL_OFFSET 1
+#define HPIPE_LOOPBACK_SEL_MASK (0x7 << HPIPE_LOOPBACK_SEL_OFFSET)
+
+#define HPIPE_SYNC_PATTERN_REG 0x090
+
+#define HPIPE_INTERFACE_REG 0x94
+#define HPIPE_INTERFACE_GEN_MAX_OFFSET 10
+#define HPIPE_INTERFACE_GEN_MAX_MASK (0x3 << HPIPE_INTERFACE_GEN_MAX_OFFSET)
+#define HPIPE_INTERFACE_LINK_TRAIN_OFFSET 14
+#define HPIPE_INTERFACE_LINK_TRAIN_MASK (0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET)
+
+#define HPIPE_ISOLATE_MODE_REG 0x98
+#define HPIPE_ISOLATE_MODE_GEN_RX_OFFSET 0
+#define HPIPE_ISOLATE_MODE_GEN_RX_MASK (0xf << HPIPE_ISOLATE_MODE_GEN_RX_OFFSET)
+#define HPIPE_ISOLATE_MODE_GEN_TX_OFFSET 4
+#define HPIPE_ISOLATE_MODE_GEN_TX_MASK (0xf << HPIPE_ISOLATE_MODE_GEN_TX_OFFSET)
+
+#define HPIPE_G1_SET_2_REG 0xf4
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET 0
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_MASK (0xf << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET)
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET 4
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK (0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_MASK)
+
+#define HPIPE_VTHIMPCAL_CTRL_REG 0x104
+
+#define HPIPE_PCIE_REG0 0x120
+#define HPIPE_PCIE_IDLE_SYNC_OFFSET 12
+#define HPIPE_PCIE_IDLE_SYNC_MASK (0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET)
+#define HPIPE_PCIE_SEL_BITS_OFFSET 13
+#define HPIPE_PCIE_SEL_BITS_MASK (0x3 << HPIPE_PCIE_SEL_BITS_OFFSET)
+
+#define HPIPE_LANE_ALIGN_REG 0x124
+#define HPIPE_LANE_ALIGN_OFF_OFFSET 12
+#define HPIPE_LANE_ALIGN_OFF_MASK (0x1 << HPIPE_LANE_ALIGN_OFF_OFFSET)
+
+#define HPIPE_MISC_REG 0x13C
+#define HPIPE_MISC_CLK100M_125M_OFFSET 4
+#define HPIPE_MISC_CLK100M_125M_MASK (0x1 << HPIPE_MISC_CLK100M_125M_OFFSET)
+#define HPIPE_MISC_ICP_FORCE_OFFSET 5
+#define HPIPE_MISC_ICP_FORCE_MASK (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET)
+#define HPIPE_MISC_TXDCLK_2X_OFFSET 6
+#define HPIPE_MISC_TXDCLK_2X_MASK (0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET)
+#define HPIPE_MISC_CLK500_EN_OFFSET 7
+#define HPIPE_MISC_CLK500_EN_MASK (0x1 << HPIPE_MISC_CLK500_EN_OFFSET)
+#define HPIPE_MISC_REFCLK_SEL_OFFSET 10
+#define HPIPE_MISC_REFCLK_SEL_MASK (0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET)
+
+#define HPIPE_RX_CONTROL_1_REG 0x140
+#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET 11
+#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK (0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET)
+#define HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET 12
+#define HPIPE_RX_CONTROL_1_CLK8T_EN_MASK (0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET)
+
+#define HPIPE_PWR_CTR_REG 0x148
+#define HPIPE_PWR_CTR_RST_DFE_OFFSET 0
+#define HPIPE_PWR_CTR_RST_DFE_MASK (0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET)
+#define HPIPE_PWR_CTR_SFT_RST_OFFSET 10
+#define HPIPE_PWR_CTR_SFT_RST_MASK (0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET)
+
+#define HPIPE_PLLINTP_REG1 0x150
+
+#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG 0x16C
+#define HPIPE_SMAPLER_OFFSET 12
+#define HPIPE_SMAPLER_MASK (0x1 << HPIPE_SMAPLER_OFFSET)
+
+#define HPIPE_TX_REG1_REG 0x174
+#define HPIPE_TX_REG1_TX_EMPH_RES_OFFSET 5
+#define HPIPE_TX_REG1_TX_EMPH_RES_MASK (0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET)
+#define HPIPE_TX_REG1_SLC_EN_OFFSET 10
+#define HPIPE_TX_REG1_SLC_EN_MASK (0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET)
+
+#define HPIPE_PWR_CTR_DTL_REG 0x184
+#define HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET 2
+#define HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK (0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET)
+
+#define HPIPE_RX_REG3 0x188
+
+#define HPIPE_TX_TRAIN_CTRL_0_REG 0x268
+#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET 15
+#define HPIPE_TX_TRAIN_P2P_HOLD_MASK (0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_REG 0x26C
+#define HPIPE_TX_TRAIN_CTRL_G1_OFFSET 0
+#define HPIPE_TX_TRAIN_CTRL_G1_MASK (0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET)
+#define HPIPE_TX_TRAIN_CTRL_GN1_OFFSET 1
+#define HPIPE_TX_TRAIN_CTRL_GN1_MASK (0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET)
+#define HPIPE_TX_TRAIN_CTRL_G0_OFFSET 2
+#define HPIPE_TX_TRAIN_CTRL_G0_MASK (0x1 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_4_REG 0x278
+#define HPIPE_TRX_TRAIN_TIMER_OFFSET 0
+#define HPIPE_TRX_TRAIN_TIMER_MASK (0x3FF << HPIPE_TRX_TRAIN_TIMER_OFFSET)
+
+#define HPIPE_PCIE_REG1 0x288
+#define HPIPE_PCIE_REG3 0x290
+
+#define HPIPE_TX_TRAIN_CTRL_5_REG 0x2A4
+#define HPIPE_TX_TRAIN_START_SQ_EN_OFFSET 11
+#define HPIPE_TX_TRAIN_START_SQ_EN_MASK (0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET)
+#define HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET 12
+#define HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK (0x1 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET)
+#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET 13
+#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK (0x1 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET)
+#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET 14
+#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK (0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET)
+
+#define HPIPE_TX_TRAIN_REG 0x31C
+#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET 4
+#define HPIPE_TX_TRAIN_CHK_INIT_MASK (0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET)
+#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET 7
+#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK (0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_11_REG 0x438
+#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET 6
+#define HPIPE_TX_TX_STATUS_CHECK_MODE_MASK (0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET)
+#define HPIPE_TX_NUM_OF_PRESET_OFFSET 10
+#define HPIPE_TX_NUM_OF_PRESET_MASK (0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET)
+#define HPIPE_TX_SWEEP_PRESET_EN_OFFSET 15
+#define HPIPE_TX_SWEEP_PRESET_EN_MASK (0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET)
+
+#define HPIPE_G1_SETTINGS_3_REG 0x440
+#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET 9
+#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK (0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET)
+
+#define HPIPE_G1_SETTINGS_4_REG 0x444
+#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET 8
+#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK (0x3 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET)
+
+#define HPIPE_G2_SETTINGS_3_REG 0x448
+#define HPIPE_G2_SETTINGS_4_REG 0x44C
+
+#define HPIPE_G3_SETTING_3_REG 0x450
+#define HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET 12
+#define HPIPE_G3_FFE_DEG_RES_LEVEL_MASK (0x3 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET)
+#define HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET 14
+#define HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK (0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET)
+
+#define HPIPE_G3_SETTING_4_REG 0x454
+#define HPIPE_G3_DFE_RES_OFFSET 8
+#define HPIPE_G3_DFE_RES_MASK (0x3 << HPIPE_G3_DFE_RES_OFFSET)
+
+#define HPIPE_DFE_CTRL_28_REG 0x49C
+#define HPIPE_DFE_CTRL_28_PIPE4_OFFSET 7
+#define HPIPE_DFE_CTRL_28_PIPE4_MASK (0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET)
+
+#define HPIPE_G1_SETTING_5_REG 0x538
+#define HPIPE_G1_SETTING_5_G1_ICP_OFFSET 0
+#define HPIPE_G1_SETTING_5_G1_ICP_MASK (0xf << HPIPE_G1_SETTING_5_G1_ICP_OFFSET)
+
+#define HPIPE_LANE_CONFIG0_REG 0x600
+#define HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET 0
+#define HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK (0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET)
+
+#define HPIPE_LANE_CONFIG1_REG 0x604
+#define HPIPE_LANE_CONFIG1_MAX_PLL_OFFSET 9
+#define HPIPE_LANE_CONFIG1_MAX_PLL_MASK (0x1 << HPIPE_LANE_CONFIG1_MAX_PLL_OFFSET)
+#define HPIPE_LANE_CONFIG1_GEN2_PLL_OFFSET 10
+#define HPIPE_LANE_CONFIG1_GEN2_PLL_MASK (0x1 << HPIPE_LANE_CONFIG1_GEN2_PLL_OFFSET)
+
+#define HPIPE_LANE_STATUS1_REG 0x60C
+#define HPIPE_LANE_STATUS1_PCLK_EN_OFFSET 0
+#define HPIPE_LANE_STATUS1_PCLK_EN_MASK (0x1 << HPIPE_LANE_STATUS1_PCLK_EN_OFFSET)
+
+#define HPIPE_LANE_CFG4_REG 0x620
+#define HPIPE_LANE_CFG4_DFE_CTRL_OFFSET 0
+#define HPIPE_LANE_CFG4_DFE_CTRL_MASK (0x7 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET)
+#define HPIPE_LANE_CFG4_DFE_OVER_OFFSET 6
+#define HPIPE_LANE_CFG4_DFE_OVER_MASK (0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET)
+#define HPIPE_LANE_CFG4_SSC_CTRL_OFFSET 7
+#define HPIPE_LANE_CFG4_SSC_CTRL_MASK (0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET)
+
+#define HPIPE_LANE_EQU_CONFIG_0_REG 0x69C
+#define HPIPE_CFG_PHY_RC_EP_OFFSET 12
+#define HPIPE_CFG_PHY_RC_EP_MASK (0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET)
+
+#define HPIPE_LANE_EQ_CFG1_REG 0x6a0
+#define HPIPE_CFG_UPDATE_POLARITY_OFFSET 12
+#define HPIPE_CFG_UPDATE_POLARITY_MASK (0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET)
+
+#define HPIPE_RST_CLK_CTRL_REG 0x704
+#define HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET 0
+#define HPIPE_RST_CLK_CTRL_PIPE_RST_MASK (0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET)
+#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET 2
+#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK (0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET)
+#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET 3
+#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK (0x1 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET)
+#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET 9
+#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK (0x1 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET)
+
+#define HPIPE_TST_MODE_CTRL_REG 0x708
+#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET 2
+#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK (0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET)
+
+#define HPIPE_CLK_SRC_LO_REG 0x70c
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET 1
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK (0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET)
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET 2
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK (0x3 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET)
+#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET 5
+#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK (0x7 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET)
+
+#define HPIPE_CLK_SRC_HI_REG 0x710
+#define HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET 0
+#define HPIPE_CLK_SRC_HI_LANE_STRT_MASK (0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET)
+#define HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET 1
+#define HPIPE_CLK_SRC_HI_LANE_BREAK_MASK (0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET)
+#define HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET 2
+#define HPIPE_CLK_SRC_HI_LANE_MASTER_MASK (0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET)
+#define HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET 7
+#define HPIPE_CLK_SRC_HI_MODE_PIPE_MASK (0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET)
+
+#define HPIPE_GLOBAL_MISC_CTRL 0x718
+#define HPIPE_GLOBAL_PM_CTRL 0x740
+#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET 0
+#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK (0xFF << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET)
+
+#endif /* _COMPHY_H_ */
+
diff --git a/drivers/marvell/dw-pcie-ep.c b/drivers/marvell/dw-pcie-ep.c
new file mode 100644
index 00000000..ed8e72e2
--- /dev/null
+++ b/drivers/marvell/dw-pcie-ep.c
@@ -0,0 +1,178 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <mmio.h>
+
+#define PCIE_CFG_VENDOR 0x0
+#define PCIE_CFG_DEVICE 0x2
+#define PCIE_CFG_CMD 0x4
+#define PCIE_CFG_CMD_IO_EN (1 << 0)
+#define PCIE_CFG_CMD_MEM_EN (1 << 1)
+#define PCIE_CFG_CMD_MASTER_EN (1 << 2)
+#define PCIE_CFG_STATUS 0x6
+
+#define PCIE_GLOBAL_CONTROL 0x8000
+#define PCIE_CFG_RETRY_EN (1 << 9)
+#define PCIE_APP_LTSSM_EN (1 << 2)
+#define PCIE_DEVICE_TYPE_OFFSET (4)
+#define PCIE_DEVICE_TYPE_MASK (0xF)
+#define PCIE_DEVICE_TYPE_EP (0x0) /* Endpoint */
+#define PCIE_DEVICE_TYPE_LEP (0x1) /* Legacy endpoint */
+#define PCIE_DEVICE_TYPE_RC (0x4) /* Root complex */
+
+#define PCIE_LINK_CTL_2 0xA0
+#define TARGET_LINK_SPEED_MASK 0xF
+#define PCIE_LINK_CAPABILITY 0x7C
+
+#define PCIE_GEN3_EQU_CTRL 0x8A8
+#define GEN3_EQU_EVAL_2MS_DISABLE (1 << 5)
+
+#define PCIE_ARCACHE_TRC 0x8050
+#define PCIE_AWCACHE_TRC 0x8054
+#define ARCACHE_SHAREABLE_CACHEABLE 0x3511
+#define AWCACHE_SHAREABLE_CACHEABLE 0x5311
+
+#define LINK_SPEED_GEN_1 0x1
+#define LINK_SPEED_GEN_2 0x2
+#define LINK_SPEED_GEN_3 0x3
+
+/* iATU registers */
+#define PCIE_IATU_VIEWPORT 0x900
+#define PCIE_IATU_CR1 0x904
+#define PCIE_IATU_CR2 0x908
+#define PCIE_IATU_CR2_EN (0x1 << 31)
+#define PCIE_IATU_LOWER_BASE 0x90C
+#define PCIE_IATU_UPPER_BASE 0x910
+#define PCIE_IATU_LIMIT 0x914
+#define PCIE_IATU_LOWER_TARGET 0x918
+#define PCIE_IATU_UPPER_TARGET 0x91C
+
+#define DW_OUTBOUND_ATU_BASE 0x8000000000ull
+#define DW_OUTBOUND_ATU_SIZE 0x100000000ull
+#define DW_OUTBOUND_ATU_TARGET 0x0
+
+
+void dw_pcie_configure(uintptr_t regs_base, uint32_t cap_speed)
+{
+ uint32_t reg;
+
+ /* Set link to GEN 3 */;
+ reg = mmio_read_32(regs_base + PCIE_LINK_CTL_2);
+ reg &= ~TARGET_LINK_SPEED_MASK;
+ reg |= cap_speed;
+ mmio_write_32(regs_base + PCIE_LINK_CTL_2, reg);
+
+ reg = mmio_read_32(regs_base + PCIE_LINK_CAPABILITY);
+ reg &= ~TARGET_LINK_SPEED_MASK;
+ reg |= cap_speed;
+ mmio_write_32(regs_base + PCIE_LINK_CAPABILITY, reg);
+
+ reg = mmio_read_32(regs_base + PCIE_GEN3_EQU_CTRL);
+ reg |= GEN3_EQU_EVAL_2MS_DISABLE;
+ mmio_write_32(regs_base + PCIE_GEN3_EQU_CTRL, reg);
+}
+
+int dw_pcie_link_up(uintptr_t regs_base, uint32_t cap_speed, int is_end_point)
+{
+ uint32_t reg;
+
+ /* Disable LTSSM state machine to enable configuration */
+ reg = mmio_read_32(regs_base + PCIE_GLOBAL_CONTROL);
+ reg &= ~(PCIE_APP_LTSSM_EN);
+ reg &= ~(PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_OFFSET);
+ if (!is_end_point)
+ reg |= (PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_OFFSET);
+ mmio_write_32(regs_base + PCIE_GLOBAL_CONTROL, reg);
+
+ /* Set the PCIe master AXI attributes */
+ mmio_write_32(regs_base + PCIE_ARCACHE_TRC, ARCACHE_SHAREABLE_CACHEABLE);
+ mmio_write_32(regs_base + PCIE_AWCACHE_TRC, AWCACHE_SHAREABLE_CACHEABLE);
+
+ /* DW pre link configurations */
+ dw_pcie_configure(regs_base, cap_speed);
+
+ /* Configuration done. Start LTSSM */
+ reg = mmio_read_32(regs_base + PCIE_GLOBAL_CONTROL);
+ reg |= PCIE_APP_LTSSM_EN;
+ mmio_write_32(regs_base + PCIE_GLOBAL_CONTROL, reg);
+
+ /* As the end-point we dont need to check if a
+ * link was established*/
+
+ return 1;
+}
+
+void dw_pcie_open_out_atu(uintptr_t dw_base, int win_id, uint64_t local_base,
+ uint64_t remote_base, uint64_t size)
+{
+ mmio_write_32(dw_base + PCIE_IATU_VIEWPORT, win_id);
+ mmio_write_32(dw_base + PCIE_IATU_LOWER_BASE, local_base & UINT32_MAX);
+ mmio_write_32(dw_base + PCIE_IATU_UPPER_BASE, local_base >> 32);
+ mmio_write_32(dw_base + PCIE_IATU_LOWER_TARGET, remote_base & UINT32_MAX);
+ mmio_write_32(dw_base + PCIE_IATU_UPPER_TARGET, remote_base >> 32);
+ mmio_write_32(dw_base + PCIE_IATU_LIMIT, size - 1);
+ mmio_write_32(dw_base + PCIE_IATU_CR2, PCIE_IATU_CR2_EN);
+}
+
+void dw_pcie_master_enable(uintptr_t dw_base)
+{
+ mmio_write_32(dw_base + PCIE_CFG_CMD, PCIE_CFG_CMD_MEM_EN |
+ PCIE_CFG_CMD_IO_EN |
+ PCIE_CFG_CMD_MASTER_EN);
+}
+
+void dw_pcie_delay_cfg(uintptr_t dw_base)
+{
+ uint32_t ctrl;
+ ctrl = mmio_read_32(dw_base + PCIE_GLOBAL_CONTROL);
+ ctrl |= PCIE_CFG_RETRY_EN;
+ mmio_write_32(dw_base + PCIE_GLOBAL_CONTROL, ctrl);
+}
+
+void dw_pcie_ep_init(uintptr_t dw_base, uint8_t delay_cfg, uint8_t master_en)
+{
+ dw_pcie_link_up(dw_base, LINK_SPEED_GEN_3, 1);
+
+ if (master_en) {
+ dw_pcie_open_out_atu(dw_base, 0, DW_OUTBOUND_ATU_BASE,
+ DW_OUTBOUND_ATU_TARGET, DW_OUTBOUND_ATU_SIZE);
+ dw_pcie_master_enable(dw_base);
+ }
+
+ if (delay_cfg)
+ dw_pcie_delay_cfg(dw_base);
+
+ return;
+}
diff --git a/drivers/marvell/i2c/a8k_i2c.c b/drivers/marvell/i2c/a8k_i2c.c
new file mode 100644
index 00000000..1356fc07
--- /dev/null
+++ b/drivers/marvell/i2c/a8k_i2c.c
@@ -0,0 +1,563 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+/* This driver provides I2C support for A8K */
+
+#include <plat_def.h>
+#include <debug.h>
+#include <mmio.h>
+#include <delay_timer.h>
+#include <a8k_i2c.h>
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+#define DEBUG_I2C
+#endif
+
+#define CONFIG_SYS_TCLK 250000000
+#define CONFIG_SYS_I2C_SPEED 100000
+#define CONFIG_SYS_I2C_SLAVE 0x0
+#define I2C_TIMEOUT_VALUE 0x500
+#define I2C_MAX_RETRY_CNT 1000
+#define I2C_CMD_WRITE 0x0
+#define I2C_CMD_READ 0x1
+
+#define I2C_DATA_ADDR_7BIT_OFFS 0x1
+#define I2C_DATA_ADDR_7BIT_MASK (0xFF << I2C_DATA_ADDR_7BIT_OFFS)
+
+#define I2C_CONTROL_ACK 0x00000004
+#define I2C_CONTROL_IFLG 0x00000008
+#define I2C_CONTROL_STOP 0x00000010
+#define I2C_CONTROL_START 0x00000020
+#define I2C_CONTROL_TWSIEN 0x00000040
+#define I2C_CONTROL_INTEN 0x00000080
+
+#define I2C_STATUS_START 0x08
+#define I2C_STATUS_REPEATED_START 0x10
+#define I2C_STATUS_ADDR_W_ACK 0x18
+#define I2C_STATUS_DATA_W_ACK 0x28
+#define I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER 0x38
+#define I2C_STATUS_ADDR_R_ACK 0x40
+#define I2C_STATUS_DATA_R_ACK 0x50
+#define I2C_STATUS_DATA_R_NAK 0x58
+#define I2C_STATUS_LOST_ARB_GENERAL_CALL 0x78
+#define I2C_STATUS_IDLE 0xF8
+
+#define EPERM 1 /* Operation not permitted */
+#define EAGAIN 11 /* Try again */
+#define ETIMEDOUT 110 /* Connection timed out */
+
+struct marvell_i2c_regs {
+ uint32_t slave_address;
+ uint32_t data;
+ uint32_t control;
+ union {
+ uint32_t status; /* when reading */
+ uint32_t baudrate; /* when writing */
+ } u;
+ uint32_t xtnd_slave_addr;
+ uint32_t reserved[2];
+ uint32_t soft_reset;
+};
+
+static struct marvell_i2c_regs *base;
+
+static int marvell_i2c_lost_arbitration(uint32_t *status)
+{
+ *status = mmio_read_32((uintptr_t)&base->u.status);
+ if ((I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER == *status) || (I2C_STATUS_LOST_ARB_GENERAL_CALL == *status))
+ return -EAGAIN;
+
+ return 0;
+}
+
+static void marvell_i2c_interrupt_clear(void)
+{
+ uint32_t reg;
+
+ /* Wait for 1 ms to prevent I2C register write after write issues */
+ udelay(1000);
+ reg = mmio_read_32((uintptr_t)&base->control);
+ reg &= ~(I2C_CONTROL_IFLG);
+ mmio_write_32((uintptr_t)&base->control, reg);
+ /* Wait for 1 ms for the clear to take effect */
+ udelay(1000);
+
+ return;
+}
+
+static int marvell_i2c_interrupt_get(void)
+{
+ uint32_t reg;
+
+ /* get the interrupt flag bit */
+ reg = mmio_read_32((uintptr_t)&base->control);
+ reg &= I2C_CONTROL_IFLG;
+ return reg && I2C_CONTROL_IFLG;
+}
+
+static int marvell_i2c_wait_interrupt(void)
+{
+ uint32_t timeout = 0;
+ while (!marvell_i2c_interrupt_get() && (timeout++ < I2C_TIMEOUT_VALUE))
+ ;
+ if (timeout >= I2C_TIMEOUT_VALUE)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int marvell_i2c_start_bit_set(void)
+{
+ int is_int_flag = 0;
+ uint32_t status;
+
+ if (marvell_i2c_interrupt_get())
+ is_int_flag = 1;
+
+ /* set start bit */
+ mmio_write_32((uintptr_t)&base->control, mmio_read_32((uintptr_t)&base->control) | I2C_CONTROL_START);
+
+ /* in case that the int flag was set before i.e. repeated start bit */
+ if (is_int_flag) {
+ INFO("%s: repeated start Bit\n", __func__);
+ marvell_i2c_interrupt_clear();
+ }
+
+ if (marvell_i2c_wait_interrupt()) {
+ ERROR("Start clear bit timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ /* check that start bit went down */
+ if ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_START) != 0) {
+ ERROR("Start bit didn't went down\n");
+ return -EPERM;
+ }
+
+ /* check the status */
+ if (marvell_i2c_lost_arbitration(&status)) {
+ INFO("%s - %d: Lost arbitration, got status %x\n", __func__, __LINE__, status);
+ return -EAGAIN;
+ }
+ if ((status != I2C_STATUS_START) && (status != I2C_STATUS_REPEATED_START)) {
+ ERROR("Got status %x after enable start bit.\n", status);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int marvell_i2c_stop_bit_set(void)
+{
+ int timeout;
+ uint32_t status;
+
+ /* Generate stop bit */
+ mmio_write_32((uintptr_t)&base->control, mmio_read_32((uintptr_t)&base->control) | I2C_CONTROL_STOP);
+ marvell_i2c_interrupt_clear();
+
+ timeout = 0;
+ /* Read control register, check the control stop bit */
+ while ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) && (timeout++ < I2C_TIMEOUT_VALUE))
+ ;
+ if (timeout >= I2C_TIMEOUT_VALUE) {
+ ERROR("Stop bit didn't went down\n");
+ return -ETIMEDOUT;
+ }
+
+ /* check that stop bit went down */
+ if ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) != 0) {
+ ERROR("Stop bit didn't went down\n");
+ return -EPERM;
+ }
+
+ /* check the status */
+ if (marvell_i2c_lost_arbitration(&status)) {
+ INFO("%s - %d: Lost arbitration, got status %x\n", __func__, __LINE__, status);
+ return -EAGAIN;
+ }
+ if (status != I2C_STATUS_IDLE) {
+ ERROR("Got status %x after enable stop bit.\n", status);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int marvell_i2c_address_set(uint8_t chain, int command)
+{
+ uint32_t reg, status;
+
+ reg = (chain << I2C_DATA_ADDR_7BIT_OFFS) & I2C_DATA_ADDR_7BIT_MASK;
+ reg |= command;
+ mmio_write_32((uintptr_t)&base->data, reg);
+ udelay(1000);
+
+ marvell_i2c_interrupt_clear();
+
+ if (marvell_i2c_wait_interrupt()) {
+ ERROR("Start clear bit timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ /* check the status */
+ if (marvell_i2c_lost_arbitration(&status)) {
+ INFO("%s - %d: Lost arbitration, got status %x\n", __func__, __LINE__, status);
+ return -EAGAIN;
+ }
+ if (((status != I2C_STATUS_ADDR_R_ACK) && (command == I2C_CMD_READ)) ||
+ ((status != I2C_STATUS_ADDR_W_ACK) && (command == I2C_CMD_WRITE))) {
+ /* only in debug, since in boot we try to read the SPD of both DRAM, and we don't
+ want error messages in case DIMM doesn't exist. */
+ INFO("%s: ERROR - status %x addr in %s mode.\n", __func__, status, (command == I2C_CMD_WRITE) ?
+ "Write" : "Read");
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static unsigned int marvell_i2c_bus_speed_set(unsigned int requested_speed)
+{
+ unsigned int n, m, freq, margin, min_margin = 0xffffffff;
+ unsigned int actual_n = 0, actual_m = 0;
+ int val;
+
+ /* Calucalte N and M for the TWSI clock baud rate */
+ for (n = 0; n < 8; n++) {
+ for (m = 0; m < 16; m++) {
+ freq = CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n));
+ val = requested_speed - freq;
+ margin = (val > 0) ? val : -val;
+
+ if ((freq <= requested_speed) && (margin < min_margin)) {
+ min_margin = margin;
+ actual_n = n;
+ actual_m = m;
+ }
+ }
+ }
+ INFO("%s: actual_n = %u, actual_m = %u\n", __func__, actual_n, actual_m);
+ /* Set the baud rate */
+ mmio_write_32((uintptr_t)&base->u.baudrate, (actual_m << 3) | actual_n);
+
+ return 0;
+}
+
+#ifdef DEBUG_I2C
+static int marvell_i2c_probe(uint8_t chip)
+{
+ int ret = 0;
+
+ ret = marvell_i2c_start_bit_set();
+ if (ret != 0) {
+ marvell_i2c_stop_bit_set();
+ ERROR("%s - %d: %s", __func__, __LINE__, "marvell_i2c_start_bit_set failed\n");
+ return -EPERM;
+ }
+
+ ret = marvell_i2c_address_set(chip, I2C_CMD_WRITE);
+ if (ret != 0) {
+ marvell_i2c_stop_bit_set();
+ INFO("%s - %d: %s", __func__, __LINE__, "marvell_i2c_address_set failed\n");
+ return -EPERM;
+ }
+
+ marvell_i2c_stop_bit_set();
+
+ INFO("%s: successful I2C probe\n", __func__);
+
+ return ret;
+}
+#endif
+
+/* regular i2c transaction */
+static int marvell_i2c_data_receive(uint8_t *p_block, uint32_t block_size)
+{
+ uint32_t reg, status, block_size_read = block_size;
+
+ /* Wait for cause interrupt */
+ if (marvell_i2c_wait_interrupt()) {
+ ERROR("Start clear bit timeout\n");
+ return -ETIMEDOUT;
+ }
+ while (block_size_read) {
+ if (block_size_read == 1) {
+ reg = mmio_read_32((uintptr_t)&base->control);
+ reg &= ~(I2C_CONTROL_ACK);
+ mmio_write_32((uintptr_t)&base->control, reg);
+ }
+ marvell_i2c_interrupt_clear();
+
+ if (marvell_i2c_wait_interrupt()) {
+ ERROR("Start clear bit timeout\n");
+ return -ETIMEDOUT;
+ }
+ /* check the status */
+ if (marvell_i2c_lost_arbitration(&status)) {
+ INFO("%s - %d: Lost arbitration, got status %x\n", __func__, __LINE__, status);
+ return -EAGAIN;
+ }
+ if ((status != I2C_STATUS_DATA_R_ACK) && (block_size_read != 1)) {
+ ERROR("Status %x in read transaction\n", status);
+ return -EPERM;
+ }
+ if ((status != I2C_STATUS_DATA_R_NAK) && (block_size_read == 1)) {
+ ERROR("Status %x in Rd Terminate\n", status);
+ return -EPERM;
+ }
+
+ /* read the data */
+ *p_block = (uint8_t) mmio_read_32((uintptr_t)&base->data);
+ INFO("%s: place %d read %x\n", __func__, block_size - block_size_read, *p_block);
+ p_block++;
+ block_size_read--;
+ }
+
+ return 0;
+}
+
+static int marvell_i2c_data_transmit(uint8_t *p_block, uint32_t block_size)
+{
+ uint32_t status, block_size_write = block_size;
+
+ if (marvell_i2c_wait_interrupt()) {
+ ERROR("Start clear bit timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ while (block_size_write) {
+ /* write the data */
+ mmio_write_32((uintptr_t)&base->data, (uint32_t) *p_block);
+ INFO("%s: index = %d, data = %x\n", __func__, block_size - block_size_write, *p_block);
+ p_block++;
+ block_size_write--;
+
+ marvell_i2c_interrupt_clear();
+
+ if (marvell_i2c_wait_interrupt()) {
+ ERROR("Start clear bit timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ /* check the status */
+ if (marvell_i2c_lost_arbitration(&status)) {
+ INFO("%s - %d: Lost arbitration, got status %x\n", __func__, __LINE__, status);
+ return -EAGAIN;
+ }
+ if (status != I2C_STATUS_DATA_W_ACK) {
+ ERROR("Status %x in write transaction\n", status);
+ return -EPERM;
+ }
+ }
+
+ return 0;
+}
+
+static int marvell_i2c_target_offset_set(uint8_t chip, uint32_t addr, int alen)
+{
+ uint8_t off_block[2];
+ uint32_t off_size;
+
+ if (alen == 2) { /* 2-byte addresses support */
+ off_block[0] = (addr >> 8) & 0xff;
+ off_block[1] = addr & 0xff;
+ off_size = 2;
+ } else { /* 1-byte addresses support */
+ off_block[0] = addr & 0xff;
+ off_size = 1;
+ }
+ INFO("%s: off_size = %x addr1 = %x addr2 = %x\n", __func__, off_size, off_block[0], off_block[1]);
+ return marvell_i2c_data_transmit(off_block, off_size);
+}
+
+/* ------------------------------------------------------------------------ */
+/* API Functions */
+/* ------------------------------------------------------------------------ */
+void i2c_init(void *i2c_base)
+{
+ /* For I2C speed and slave address, now we do not set them since
+ * we just provide the working speed and slave address in plat_def.h
+ * for i2c_init
+ */
+ base = (struct marvell_i2c_regs *)i2c_base;
+
+ /* Reset the I2C logic */
+ mmio_write_32((uintptr_t)&base->soft_reset, 0);
+
+ udelay(2000);
+
+ marvell_i2c_bus_speed_set(CONFIG_SYS_I2C_SPEED);
+
+ /* Enable the I2C and slave */
+ mmio_write_32((uintptr_t)&base->control, I2C_CONTROL_TWSIEN | I2C_CONTROL_ACK);
+
+ /* set the I2C slave address */
+ mmio_write_32((uintptr_t)&base->xtnd_slave_addr, 0);
+ mmio_write_32((uintptr_t)&base->slave_address, CONFIG_SYS_I2C_SLAVE);
+
+ /* unmask I2C interrupt */
+ mmio_write_32((uintptr_t)&base->control, mmio_read_32((uintptr_t)&base->control) | I2C_CONTROL_INTEN);
+
+ udelay(1000);
+}
+
+/*
+ * i2c_read: - Read multiple bytes from an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip: address of the chip which is to be read
+ * @addr: i2c data address within the chip
+ * @alen: length of the i2c data address (1..2 bytes)
+ * @buffer: where to write the data
+ * @len: how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_read(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len)
+{
+ int ret = 0;
+ uint32_t counter = 0;
+
+#ifdef DEBUG_I2C
+ marvell_i2c_probe(chip);
+#endif
+
+ do {
+ if (ret != -EAGAIN && ret) {
+ ERROR("i2c transaction failed, after %d retries\n", counter);
+ marvell_i2c_stop_bit_set();
+ return ret;
+ }
+
+ /* wait for 1 ms for the interrupt clear to take effect */
+ if (counter > 0)
+ udelay(1000);
+ counter++;
+
+ ret = marvell_i2c_start_bit_set();
+ if (ret)
+ continue;
+
+ /* if EEPROM device */
+ if (alen != 0) {
+ ret = marvell_i2c_address_set(chip, I2C_CMD_WRITE);
+ if (ret)
+ continue;
+
+ ret = marvell_i2c_target_offset_set(chip, addr, alen);
+ if (ret)
+ continue;
+ ret = marvell_i2c_start_bit_set();
+ if (ret)
+ continue;
+ }
+
+ ret = marvell_i2c_address_set(chip, I2C_CMD_READ);
+ if (ret)
+ continue;
+
+ ret = marvell_i2c_data_receive(buffer, len);
+ if (ret)
+ continue;
+
+ ret = marvell_i2c_stop_bit_set();
+ } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT));
+
+ if (counter == I2C_MAX_RETRY_CNT)
+ ERROR("I2C transactions failed, got EAGAIN %d times\n", I2C_MAX_RETRY_CNT);
+ mmio_write_32((uintptr_t)&base->control, mmio_read_32((uintptr_t)&base->control) | I2C_CONTROL_ACK);
+
+ udelay(1000);
+ return 0;
+}
+
+/*
+ * i2c_write: - Write multiple bytes to an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip: address of the chip which is to be written
+ * @addr: i2c data address within the chip
+ * @alen: length of the i2c data address (1..2 bytes)
+ * @buffer: where to find the data to be written
+ * @len: how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_write(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len)
+{
+ int ret = 0;
+ uint32_t counter = 0;
+
+ do {
+ if (ret != -EAGAIN && ret) {
+ ERROR("i2c transaction failed\n");
+ marvell_i2c_stop_bit_set();
+ return ret;
+ }
+ /* wait for 1 ms for the interrupt clear to take effect */
+ if (counter > 0)
+ udelay(1000);
+ counter++;
+
+ ret = marvell_i2c_start_bit_set();
+ if (ret)
+ continue;
+
+ ret = marvell_i2c_address_set(chip, I2C_CMD_WRITE);
+ if (ret)
+ continue;
+
+ /* if EEPROM device */
+ if (alen != 0) {
+ ret = marvell_i2c_target_offset_set(chip, addr, alen);
+ if (ret)
+ continue;
+ }
+
+ ret = marvell_i2c_data_transmit(buffer, len);
+ if (ret)
+ continue;
+
+ ret = marvell_i2c_stop_bit_set();
+ } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT));
+
+ if (counter == I2C_MAX_RETRY_CNT)
+ ERROR("I2C transactions failed, got EAGAIN %d times\n", I2C_MAX_RETRY_CNT);
+
+ udelay(1000);
+ return 0;
+}
diff --git a/drivers/marvell/icu.c b/drivers/marvell/icu.c
new file mode 100644
index 00000000..12e95048
--- /dev/null
+++ b/drivers/marvell/icu.c
@@ -0,0 +1,143 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <mmio.h>
+#include <icu.h>
+
+#define ICU_SET_SPI_AL(x) (0x10 + (0x10 * x))
+#define ICU_SET_SPI_AH(x) (0x14 + (0x10 * x))
+#define ICU_CLR_SPI_AL(x) (0x18 + (0x10 * x))
+#define ICU_CLR_SPI_AH(x) (0x1c + (0x10 * x))
+#define ICU_INT_CFG(x) (0x100 + 4 * x)
+
+#define ICU_INT_ENABLE_OFFSET (24)
+#define ICU_IS_EDGE_OFFSET (28)
+#define ICU_GROUP_OFFSET (29)
+
+enum icu_group {
+ ICU_GRP_NSR = 0,
+ ICU_GRP_SR = 1,
+ ICU_GRP_LPI = 2,
+ ICU_GRP_VLPI = 3,
+ ICU_GRP_SEI = 4,
+ ICU_GRP_REI = 5,
+ ICU_GRP_MAX,
+};
+
+struct icu_msi {
+ enum icu_group group;
+ uintptr_t set_spi_addr;
+ uintptr_t clr_spi_addr;
+};
+
+#define MAX_ICU_IRQS 207
+
+/* Allocate the MSI address per interrupt group,
+ * unsopprted groups get NULL address */
+static struct icu_msi msi_addr[] = {
+ {ICU_GRP_NSR, 0xf03f0040, 0xf03f0048}, /* Non secure interrupts*/
+ {ICU_GRP_SR, 0, 0x0}, /* Secure interrupts */
+ {ICU_GRP_LPI, 0x0, 0x0}, /* LPI interrupts */
+ {ICU_GRP_VLPI, 0x0, 0x0}, /* Virtual LPI interrupts */
+ {ICU_GRP_SEI, 0xf03f0230, 0xf03f0230}, /* System error interrupts */
+ {ICU_GRP_REI, 0xf03f0270, 0xf03f0270}, /* RAM error interrupts */
+};
+
+static void icu_clear_irq(uintptr_t icu_base, int nr)
+{
+ mmio_write_32(icu_base + ICU_INT_CFG(nr), 0);
+}
+
+static void icu_set_irq(uintptr_t icu_base, const struct icu_irq *irq,
+ uint32_t spi_base, enum icu_group group)
+{
+ uint32_t icu_int;
+
+ icu_int = (irq->spi_id + spi_base) | (1 << ICU_INT_ENABLE_OFFSET);
+ icu_int |= irq->is_edge << ICU_IS_EDGE_OFFSET;
+ icu_int |= group << ICU_GROUP_OFFSET;
+
+ mmio_write_32(icu_base + ICU_INT_CFG(irq->icu_id), icu_int);
+}
+
+/*
+ * This function uses 2 spi values to initialize the ICU
+ * spi_base: used to set the base of the SPI id in the MSI message
+ * generated by the ICU. AP806-Z1 required spi_base=64 while
+ * AP806-A0 uses spi_base=0
+ * spi_offset: used to shift the multi instance interrupts between CP-0
+ * and CP-1
+ */
+void icu_init(int cp_index, int spi_base, int spi_offset,
+ const struct icu_config *config)
+{
+ int i;
+ const struct icu_irq *irq;
+ struct icu_msi *msi;
+ uintptr_t icu_base = MVEBU_ICU_REG_BASE(cp_index);
+
+ /* Set the addres for SET_SPI and CLR_SPI registers in AP */
+ msi = msi_addr;
+ for (i = 0; i < ICU_GRP_MAX; i++, msi++) {
+ mmio_write_32(icu_base + ICU_SET_SPI_AL(msi->group), msi->set_spi_addr & 0xFFFFFFFF);
+ mmio_write_32(icu_base + ICU_SET_SPI_AH(msi->group), msi->set_spi_addr >> 32);
+ mmio_write_32(icu_base + ICU_CLR_SPI_AL(msi->group), msi->clr_spi_addr & 0xFFFFFFFF);
+ mmio_write_32(icu_base + ICU_CLR_SPI_AH(msi->group), msi->clr_spi_addr >> 32);
+ }
+
+ /* Mask all ICU interrupts */
+ for (i = 0; i < MAX_ICU_IRQS; i++)
+ icu_clear_irq(icu_base, i);
+
+ /* Configure the ICU interrupt lines */
+ /* Multi instance interrupts use different SPI ID for CP-1*/
+ irq = config->ns_multi.map;
+ for (i = 0; i < config->ns_multi.size; i++, irq++)
+ icu_set_irq(icu_base, irq, spi_base + spi_offset, ICU_GRP_NSR);
+
+ irq = config->ns_single.map;
+ for (i = 0; i < config->ns_single.size; i++, irq++)
+ icu_set_irq(icu_base, irq, spi_base, ICU_GRP_NSR);
+
+ irq = config->sei.map;
+ for (i = 0; i < config->sei.size; i++, irq++)
+ icu_set_irq(icu_base, irq, spi_base, ICU_GRP_SEI);
+
+ irq = config->rei.map;
+ for (i = 0; i < config->rei.size; i++, irq++)
+ icu_set_irq(icu_base, irq, spi_base, ICU_GRP_REI);
+
+ return;
+}
diff --git a/drivers/marvell/iob.c b/drivers/marvell/iob.c
new file mode 100644
index 00000000..2a559c25
--- /dev/null
+++ b/drivers/marvell/iob.c
@@ -0,0 +1,206 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <debug.h>
+#include <mmio.h>
+#include <mvebu.h>
+#include <iob.h>
+#include <plat_config.h>
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+#define DEBUG_ADDR_MAP
+#endif
+
+/* common defines */
+#define WIN_ENABLE_BIT (0x1)
+/* Physical address of the base of the window = {AddrLow[19:0],20`h0} */
+#define ADDRESS_SHIFT (20 - 4)
+#define ADDRESS_MASK (0xFFFFFFF0)
+#define IOB_WIN_ALIGNMENT (0x100000)
+
+/* IOB registers */
+#define IOB_MAX_WIN_NUM (24)
+
+#define IOB_WIN_CR_OFFSET(win) (iob_info->iob_base + 0x0 + (0x20 * win))
+#define IOB_TARGET_ID_OFFSET (8)
+#define IOB_TARGET_ID_MASK (0xF)
+
+#define IOB_WIN_SCR_OFFSET(win) (iob_info->iob_base + 0x4 + (0x20 * win))
+#define IOB_WIN_ENA_CTRL_WRITE_SECURE (0x1)
+#define IOB_WIN_ENA_CTRL_READ_SECURE (0x2)
+#define IOB_WIN_ENA_WRITE_SECURE (0x4)
+#define IOB_WIN_ENA_READ_SECURE (0x8)
+
+#define IOB_WIN_ALR_OFFSET(win) (iob_info->iob_base + 0x8 + (0x20 * win))
+#define IOB_WIN_AHR_OFFSET(win) (iob_info->iob_base + 0xC + (0x20 * win))
+
+struct iob_configuration {
+ uintptr_t iob_base;
+ uint32_t max_win;
+};
+
+struct iob_configuration iob_config;
+struct iob_configuration *iob_info = &iob_config;
+
+static void iob_win_check(struct iob_win *win, uint32_t win_num)
+{
+ uint64_t base_addr, win_size;
+
+ /* check if address is aligned to the size */
+ base_addr = ((uint64_t)win->base_addr_high << 32) + win->base_addr_low;
+ if (IS_NOT_ALIGN(base_addr, IOB_WIN_ALIGNMENT)) {
+ base_addr = ALIGN_UP(base_addr, IOB_WIN_ALIGNMENT);
+ ERROR("Window %d: base address unaligned to 0x%x\n", win_num, IOB_WIN_ALIGNMENT);
+ printf("Align up the base address to 0x%lx\n", base_addr);
+ win->base_addr_high = (uint32_t)(base_addr >> 32);
+ win->base_addr_low = (uint32_t)(base_addr);
+ }
+
+ /* size parameter validity check */
+ win_size = ((uint64_t)win->win_size_high << 32) + win->win_size_low;
+ if (IS_NOT_ALIGN(win_size, IOB_WIN_ALIGNMENT)) {
+ win_size = ALIGN_UP(win_size, IOB_WIN_ALIGNMENT);
+ ERROR("Window %d: window size unaligned to 0x%x\n", win_num, IOB_WIN_ALIGNMENT);
+ printf("Aligning size to 0x%lx\n", win_size);
+ win->win_size_high = (uint32_t)(win_size >> 32);
+ win->win_size_low = (uint32_t)(win_size);
+ }
+}
+
+static void iob_enable_win(struct iob_win *win, uint32_t win_id)
+{
+ uint32_t iob_win_reg;
+ uint32_t alr, ahr;
+ uint64_t start_addr, end_addr;
+
+ iob_win_reg = WIN_ENABLE_BIT;
+ iob_win_reg |= (win->target_id & IOB_TARGET_ID_MASK) << IOB_TARGET_ID_OFFSET;
+ mmio_write_32(IOB_WIN_CR_OFFSET(win_id), iob_win_reg);
+
+ start_addr = ((uint64_t)win->base_addr_high << 32) + win->base_addr_low;
+ end_addr = (start_addr + (((uint64_t)win->win_size_high << 32) + win->win_size_low) - 1);
+ alr = (uint32_t)((start_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
+ ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
+
+ mmio_write_32(IOB_WIN_ALR_OFFSET(win_id), alr);
+ mmio_write_32(IOB_WIN_AHR_OFFSET(win_id), ahr);
+}
+
+#ifdef DEBUG_ADDR_MAP
+static void dump_iob(void)
+{
+ uint32_t win_id, win_cr, alr, ahr;
+ uint8_t target_id;
+ uint64_t start, end;
+ char *iob_target_name[IOB_MAX_TID] = {"CONFIG", "MCI0 ", "PEX1 ", "PEX2 ",
+ "PEX0 ", "NAND ", "RUNIT", "MCI1 "};
+
+ /* Dump all IOB windows */
+ printf("bank id target start end\n");
+ printf("----------------------------------------------------\n");
+ for (win_id = 0; win_id < iob_info->max_win; win_id++) {
+ win_cr = mmio_read_32(IOB_WIN_CR_OFFSET(win_id));
+ if (win_cr & WIN_ENABLE_BIT) {
+ target_id = (win_cr >> IOB_TARGET_ID_OFFSET) & IOB_TARGET_ID_MASK;
+ alr = mmio_read_32(IOB_WIN_ALR_OFFSET(win_id));
+ start = ((uint64_t)alr << ADDRESS_SHIFT);
+ if (win_id != 0) {
+ ahr = mmio_read_32(IOB_WIN_AHR_OFFSET(win_id));
+ end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT);
+ } else {
+ /* Window #0 size is hardcoded to 16MB, as it's
+ ** reserved for CP configuration space. */
+ end = start + (16 << 20);
+ }
+ printf("iob %02d %s 0x%016lx 0x%016lx\n"
+ , win_id, iob_target_name[target_id], start, end);
+ }
+ }
+
+ return;
+}
+#endif
+
+int init_iob(int cp_index)
+{
+ struct iob_win *win;
+ uint32_t win_id, win_reg;
+ uint32_t win_count;
+
+ INFO("Initializing IOB Address decoding\n");
+
+ /* Get the base address of the address decoding MBUS */
+ iob_info->iob_base = marvell_get_iob_reg_offs(cp_index);
+
+ /* Get the maximum number of iob windows supported */
+ iob_info->max_win = marvell_get_iob_max_win();
+ if (iob_info->max_win == 0) {
+ iob_info->max_win = IOB_MAX_WIN_NUM;
+ ERROR("IOB win num cannot be 0. Setting to default num (%d)\n", IOB_MAX_WIN_NUM);
+ }
+
+ /* Get the array of the windows and fill the map data */
+ marvell_get_iob_memory_map(&win, &win_count, cp_index);
+ if (win_count <= 0) {
+ INFO("no windows configurations found\n");
+ return 0;
+ }
+
+ /* disable all IOB windows, start from win_id = 1 because can't disable internal register window */
+ for (win_id = 1; win_id < iob_info->max_win; win_id++) {
+ win_reg = mmio_read_32(IOB_WIN_CR_OFFSET(win_id));
+ win_reg &= ~WIN_ENABLE_BIT;
+ mmio_write_32(IOB_WIN_CR_OFFSET(win_id), win_reg);
+
+ win_reg = ~IOB_WIN_ENA_CTRL_WRITE_SECURE;
+ win_reg &= ~IOB_WIN_ENA_CTRL_READ_SECURE;
+ win_reg &= ~IOB_WIN_ENA_WRITE_SECURE;
+ win_reg &= ~IOB_WIN_ENA_READ_SECURE;
+ mmio_write_32(IOB_WIN_SCR_OFFSET(win_id), win_reg);
+ }
+
+ for (win_id = 1; win_id < win_count + 1; win_id++, win++) {
+ iob_win_check(win, win_id);
+ iob_enable_win(win, win_id);
+ }
+
+#ifdef DEBUG_ADDR_MAP
+ dump_iob();
+#endif
+
+ INFO("Done IOB Address decoding Initializing\n");
+
+ return 0;
+}
diff --git a/drivers/marvell/mci.c b/drivers/marvell/mci.c
new file mode 100644
index 00000000..b9815161
--- /dev/null
+++ b/drivers/marvell/mci.c
@@ -0,0 +1,617 @@
+/*
+ * ***************************************************************************
+ * Copyright (C) 2016 Marvell International Ltd.
+ * ***************************************************************************
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Marvell nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************************
+ */
+#include <plat_def.h>
+#include <plat_marvell.h>
+#include <debug.h>
+#include <mmio.h>
+#include <mci.h>
+#include <apn806_setup.h>
+#include <delay_timer.h>
+
+enum {
+ MCI_CMD_WRITE,
+ MCI_CMD_READ
+};
+
+/* Write wrapper callback for debug:
+ * will print written data in case LOG_LEVEL >= 40
+ */
+static void mci_mmio_write_32(uintptr_t addr, uint32_t value)
+{
+ VERBOSE("Write:\t0x%x = 0x%x\n", (uint32_t)addr, value);
+ mmio_write_32(addr, value);
+}
+/* Read wrapper callback for debug:
+ * will print read data in case LOG_LEVEL >= 40
+ */
+static uint32_t mci_mmio_read_32(uintptr_t addr)
+{
+ uint32_t value;
+ value = mmio_read_32(addr);
+ VERBOSE("Read:\t0x%x = 0x%x\n", (uint32_t)addr, value);
+ return value;
+}
+
+/* MCI indirect access command completion polling:
+ * Each write/read command done via MCI indirect registers must be polled
+ * for command completions status.
+ *
+ * Returns 1 in case of error
+ * Returns 0 in case of command completed successfully.
+ */
+static int mci_poll_command_completion(int mci_index, int command_type)
+{
+ uint32_t mci_cmd_value = 0, retry_count = 100;
+ uint32_t completion_flags = MCI_INDIRECT_CTRL_CMD_DONE;
+
+ /* Read commands require validating that requested data is ready */
+ if (command_type == MCI_CMD_READ)
+ completion_flags |= MCI_INDIRECT_CTRL_DATA_READY;
+
+ do {
+ /* wait 1 ms before each polling */
+ mdelay(1);
+ mci_cmd_value = mci_mmio_read_32(MCI_ACCESS_CMD_REG(mci_index));
+ } while (((mci_cmd_value & completion_flags) != completion_flags) &&
+ (retry_count-- > 0));
+
+ if (retry_count == 0) {
+ ERROR("%s: MCI command timeout (command status = 0x%x)\n", __func__, mci_cmd_value);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Routine to enable register-mode access to PHYs over MCI0 indirect read/write*/
+static void mci_enable_phy_regs_access(int mci_index)
+{
+ uint32_t reg_data = MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE |
+ MCI_PHY_CTRL_MCI_MAJOR | MCI_PHY_CTRL_MCI_MINOR;
+
+ /* Enable PHY REG access on remote (CP, device mode, GID=2) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
+ mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* Enable PHY REG access localy (AP, host mode, GID=0) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ reg_data | MCI_PHY_CTRL_MCI_PHY_MODE_HOST);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+}
+
+/* read mci0 PHY/CTRL registers via indirect (local) access */
+static uint32_t mci_indirect_read(int reg_num, enum mci_register_type reg_type, int mci_index)
+{
+ uint32_t indirect_reg_address = MCI_INDIRECT_REG_CTRL_ADDR(reg_num) |
+ MCI_INDIRECT_CTRL_READ_CMD;
+
+ /* Access to PHY registers requires special configuration */
+ if (reg_type == MCI_REG_TYPE_PHY)
+ indirect_reg_address |= MCI_INDIRECT_CTRL_PHY_ACCESS_EN;
+
+ /* Local access - same chip */
+ indirect_reg_address |= MCI_INDIRECT_CTRL_LOCAL_PKT;
+
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), indirect_reg_address);
+ return mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_index));
+}
+
+/* Force MCI link speed to 8Gbps */
+static void mci_link_force_speed_8g(int mci_index)
+{
+ uint32_t reg_data;
+
+ /* Force link speed localy on AP PHY */
+ reg_data = PWM2_SPEED_V3_8G | PWM2_SPEED_FORCE |
+ PWM2_RX_LINE_EN | PWM2_TX_LINE_EN;
+
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_PWM2_REG_NUM) |
+ MCI_INDIRECT_CTRL_PHY_ACCESS_EN |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+
+ /* Force link speed remotely on CP PHY */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_PWM2_REG_NUM) |
+ MCI_INDIRECT_CTRL_PHY_ACCESS_EN |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
+
+ /* Enable SW power state requests control mode */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_PHY_P0_IDLE_MIN_IDLE_COUNT |
+ MCI_PHY_P0_IDLE_SW_PWR_REQ_EN |
+ MCI_PHY_P0_IDLE_SW_RETRAIN_MODE);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_P0_IDLE_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+
+ /* Toggle power state request */
+ reg_data = MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE |
+ MCI_PHY_CTRL_MCI_PHY_MODE_HOST |
+ MCI_PHY_CTRL_MCI_SLEEP_REQ |
+ MCI_PHY_CTRL_MCI_MAJOR |
+ MCI_PHY_CTRL_MCI_MINOR;
+
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+
+ reg_data &= ~MCI_PHY_CTRL_MCI_SLEEP_REQ;
+
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+
+ /* Return power state requests control mode back to HW */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_PHY_P0_IDLE_MIN_IDLE_COUNT |
+ MCI_PHY_P0_IDLE_SW_RETRAIN_MODE);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_P0_IDLE_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+
+ /* Reset all fields in link CRC control register */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_LINK_CRC_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+}
+
+/* Perform 3 configurations in one command: PCI mode, queues separation and cache bit */
+static int mci_axi_set_pcie_mode(int mci_index)
+{
+ uint32_t reg_data;
+
+ /* This configuration makes MCI IP behave consistently with AXI protocol.
+ * It should be configured at one side only (for example localy at AP).
+ * The IP takes care of performing the same configurations at MCI on another
+ * side (for example remotely at CP).
+ */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_AXI_ACCESS_PCIE_MODE |
+ MCI_AXI_ACCESS_CACHE_CHECK |
+ MCI_AXI_ACCESS_FORCE_POST_WR |
+ MCI_AXI_ACCESS_DISABLE_CLK_GATING);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_AXI_ACCESS_DATA_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT |
+ MCI_INDIRECT_CTRL_CIRCULAR_CMD);
+
+ /* if Write command was successful, verify PCIe mode */
+ if (mci_poll_command_completion(mci_index, MCI_CMD_WRITE) == 0) {
+ /* Verify the PCIe mode selected */
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_HB_CTRL_TX_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT |
+ MCI_INDIRECT_CTRL_READ_CMD);
+ /* if read was completed, verify PCIe mode */
+ if (mci_poll_command_completion(mci_index, MCI_CMD_READ) == 0) {
+ reg_data = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_index));
+ if (reg_data & MCI_HB_CTRL_TX_CTRL_PCIE_MODE)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Reduce sequence FIFO timer expiration threshold */
+static int mci_axi_set_fifo_thresh(int mci_index)
+{
+ uint32_t reg_data;
+
+ /* This configuration reduces sequence FIFO timer expiration threshold (to 0x7 instead of 0xA).
+ * In MCI 1.6 version this configuration prevents possible functional issues.
+ * In version 1.82 the configuration prevents performance degradation
+ */
+ /* Configure local AP side */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_IHB_MODE_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+
+ /* Check the command execution status */
+ reg_data = mci_mmio_read_32(MCI_ACCESS_CMD_REG(mci_index));
+ if (reg_data | MCI_INDIRECT_CTRL_CMD_DONE) {
+ /* Configure remote CP side */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_IHB_MODE_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
+
+ /* Check the command execution status */
+ reg_data = mci_mmio_read_32(MCI_ACCESS_CMD_REG(mci_index));
+ if (reg_data | MCI_INDIRECT_CTRL_CMD_DONE)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Reduce sequence FIFO timer expiration threshold for A1, including PIDI workaround */
+static int mci_axi_set_fifo_thresh_a1(int mci_index)
+{
+ uint32_t reg_data, ret = 0;
+
+ /* This configuration reduces sequence FIFO timer expiration threshold (to 0x7 instead of 0xA).
+ * In MCI 1.6 version this configuration prevents possible functional issues.
+ * In version 1.82 the configuration prevents performance degradation
+ */
+
+ /* Configure local AP side */
+ /* PIDI Workaround for entering PIDI mode */
+ reg_data = MCI_PHY_CTRL_PIDI_MODE | MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE
+ | MCI_PHY_CTRL_MCI_PHY_MODE_HOST
+ | MCI_PHY_CTRL_MCI_MAJOR | MCI_PHY_CTRL_MCI_MINOR_A1;
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* Reduce the threshold */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL_A1);
+
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_IHB_MODE_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* Exit PIDI mode */
+ reg_data = MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE | MCI_PHY_CTRL_MCI_PHY_MODE_HOST
+ | MCI_PHY_CTRL_MCI_MAJOR | MCI_PHY_CTRL_MCI_MINOR_A1;
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+
+ /* Configure remote CP side */
+ /* PIDI Workaround for entering PIDI mode */
+ reg_data = MCI_PHY_CTRL_PIDI_MODE | MCI_PHY_CTRL_MCI_MAJOR | MCI_PHY_CTRL_MCI_MINOR_A1;
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | MCI_CTRL_IHB_MODE_FWD_MOD);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* Reduce the threshold */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL_A1);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_IHB_MODE_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* Exit PIDI mode */
+ reg_data = MCI_PHY_CTRL_MCI_MAJOR | MCI_PHY_CTRL_MCI_MINOR_A1;
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | MCI_CTRL_IHB_MODE_FWD_MOD);
+
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ return ret;
+}
+
+/* Configure:
+ * 1. AP & CP TX thresholds and delta configurations
+ * 2. DLO & DLI FIFO full threshold
+ * 3. RX thresholds and delta configurations
+ * 4. CP AR and AW outstanding
+ * 5. AP AR and AW outstanding
+ */
+static int mci_axi_set_fifo_rx_tx_thresh_a1(int mci_index)
+{
+ uint32_t ret = 0;
+
+ /* AP TX thresholds and delta configurations (IHB_reg 0x1) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_TX_MEM_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* CP TX thresholds and delta configurations (IHB_reg 0x1) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_TX_MEM_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* AP DLO & DLI FIFO full threshold & Auto-Link enable (IHB_reg 0x8) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL | MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1));
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* CP DLO & DLI FIFO full threshold (IHB_reg 0x8) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* AP RX thresholds and delta configurations (IHB_reg 0x0) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_RX_MEM_CFG_REG_DEF_VAL);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_RX_MEM_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* CP RX thresholds and delta configurations (IHB_reg 0x0) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_CTRL_RX_MEM_CFG_REG_DEF_VAL);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_RX_MEM_CFG_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* AP AR & AW maximum AXI outstanding request configuration (HB_reg 0xd) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) |
+ MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(7) |
+ MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(7));
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_HB_CTRL_TX_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* CP AR & AW maximum AXI outstanding request configuration (HB_reg 0xd) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
+ MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) |
+ MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(15) |
+ MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(15));
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_HB_CTRL_TX_CTRL_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB));
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ return ret;
+}
+
+/* configure MCI to allow read & write transactions to arrive at the same time.
+ * Without the below configuration, MCI won't sent response to CPU for transactions
+ * which arrived simultaneously and will lead to CPU hang.
+ * The below will configure MCI to be able to pass transactions from/to CP/AP.
+ */
+int mci_enable_simultaneous_transactions(int mci_index)
+{
+ uint32_t ret = 0;
+
+ /* ID assignment (assigning global ID offset to CP) */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0),
+ MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(2) |
+ MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(2) |
+ MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(2));
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG) |
+ MCI_INDIRECT_CTRL_ASSIGN_CMD);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* Assigning destination ID=3 to all transactions entering from AXI at AP */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0),
+ MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) |
+ MCI_HB_CTRL_WIN0_DEST_ID(3));
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* Assigning destination ID=1 to all transactions entering from AXI at CP */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0),
+ MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) |
+ MCI_HB_CTRL_WIN0_DEST_ID(1));
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB));
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* End address to all transactions entering from AXI at AP. This will lead to
+ * get match for any AXI address, and receive destination ID=3 */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0), 0xffffffff);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
+ MCI_INDIRECT_CTRL_LOCAL_PKT);
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ /* End address to all transactions entering from AXI at CP. This will lead to
+ * get match for any AXI address, and receive destination ID=1 */
+ mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0), 0xffffffff);
+ mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+ MCI_INDIRECT_REG_CTRL_ADDR(MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) |
+ MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
+ MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB));
+ ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
+
+ return ret;
+}
+
+/* For A1 revision, configure the MCI link for performance improvement:
+ * - set MCI to support read/write transactions to arrive at the same time
+ * - Switch AXI to PCIe mode
+ * - Reduce sequence FIFO threshold
+ * - Configure RX/TX FIFO thresholds
+ *
+ * Note:
+ * We don't exit on error code from any sub routine, to try (best effort) to
+ * complete the MCI configuration.
+ * (If we exit - Bootloader will surely fail to boot)
+ */
+int mci_configure_a1(int mci_index)
+{
+ int rval;
+
+ /* set MCI to support read/write transactions to arrive at the same time */
+ rval = mci_enable_simultaneous_transactions(mci_index);
+ if (rval)
+ ERROR("Failed to set MCI for simultaneous read/write transactions\n");
+
+ /* enable PHY register mode read/write access */
+ mci_enable_phy_regs_access(mci_index);
+
+ /* Configure MCI for more consistent behavior with AXI protocol */
+ rval = mci_axi_set_pcie_mode(mci_index);
+ if (rval)
+ ERROR("Failed to set MCI to AXI PCIe mode\n");
+
+ /* reduce FIFO global threshold */
+ rval = mci_axi_set_fifo_thresh_a1(mci_index);
+ if (rval)
+ ERROR("Failed to set MCI FIFO global threshold\n");
+
+ /* configure RX/TX FIFO thresholds */
+ rval = mci_axi_set_fifo_rx_tx_thresh_a1(mci_index);
+ if (rval)
+ ERROR("Failed to set MCI RX/TX FIFO threshold\n");
+
+ return 1;
+}
+
+/* For A0 revision, Initialize the MCI link and check its status.
+ * - Configure MCI indirect access registers for register-mode access
+ * - Foce MCI link speed to 8Gbps
+ * - Switch AXI to PCIe mode
+ * - Reduce sequence FIFO threshold
+ * - Check the status of MCI link
+ * - Reset SoC on unrecoverable link fail
+ */
+int mci_link_init_a0(int mci_index)
+{
+ uint32_t ctrl_status, phy_status, link_error;
+ int rval, n;
+
+ /* enable PHY register mode read/write access */
+ mci_enable_phy_regs_access(mci_index);
+
+ INFO("Force the MCI0 link speed to 8GBps\n");
+ /* APN806-A0: Force link speed to 8Gbps */
+ mci_link_force_speed_8g(mci_index);
+
+ /* Configure MCI for more consistent behavior with AXI protocol */
+ rval = mci_axi_set_pcie_mode(mci_index);
+ if (rval)
+ ERROR("Failed to set AXI PCIe mode\n");
+
+ /* reduce FIFO threshold */
+ rval = mci_axi_set_fifo_thresh(mci_index);
+ if (rval)
+ ERROR("Failed to set FIFO threshold\n");
+
+ for (n = 0; n < LINK_READY_TIMEOUT; n++) {
+ /* MCI Controller link status*/
+ ctrl_status = mci_indirect_read(MCI_CTRL_STATUS_REG_NUM, MCI_REG_TYPE_CTRL, mci_index);
+
+ /* MCI PHY link status: PWM Control #3*/
+ phy_status = mci_indirect_read(MCI_PHY_PWM3_REG_NUM, MCI_REG_TYPE_PHY, mci_index);
+
+ if (ctrl_status == MCI_CTRL_PHY_READY)
+ break;
+ }
+
+ if (ctrl_status != MCI_CTRL_PHY_READY) {
+ ERROR(" Link failed (MCI status: 0x%x, PWM_CTRL #3 = 0x%x)\n",
+ ctrl_status, phy_status);
+ goto reboot;
+ }
+
+ link_error = (phy_status & PWM3_LINK_ERROR_MASK) >> PWM3_LINK_ERROR_OFFSET;
+ if (link_error) {
+ ERROR(" Link Error #%d: (MCI status: 0%x)\n", link_error, ctrl_status);
+ goto reboot;
+ }
+ INFO("MCI0 link is UP\n");
+
+ return 1;
+
+reboot:
+ /* Unrecoverable error, no WA exists, requires HW reset */
+ ERROR("REBOOTING...");
+ plat_marvell_system_reset();
+ /* Never reached */
+ return 0;
+}
+
+/* Initialize MCI
+ * - Performance improvements for A0 & A1
+ * - A0 revision configuration include MCI link initialization */
+int mci_initialize(int mci_index)
+{
+ INFO("MCI%d initialization:\n", mci_index);
+
+ if (apn806_rev_id_get() == APN806_REV_ID_A0)
+ return mci_link_init_a0(0);
+
+ /* Else, for A1 configure MCI for improved performance */
+ mci_configure_a1(0);
+ return 1; /* Link is always guaranteed for A1 */
+}
+
+/* MCIx indirect access register are based by default at 0xf4000000/0xf6000000
+ * to avoid conflict of internal registers of units connected via MCIx, which
+ * can be based on the same address (i.e CP1 base is also 0xf4000000),
+ * the following routines remaps the MCIx indirect bases to another domain
+ */
+void mci_remap_indirect_access_base(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < MCI_MAX_UNIT_ID; ++i) {
+ mci_mmio_write_32(MCIX4_REG_START_ADDRESS_REG(i),
+ MVEBU_MCI_REG_BASE_REMAP(i) >> MCI_REMAP_OFF_SHIFT);
+ }
+}
diff --git a/drivers/marvell/mochi/apn806_setup.c b/drivers/marvell/mochi/apn806_setup.c
new file mode 100644
index 00000000..95dff189
--- /dev/null
+++ b/drivers/marvell/mochi/apn806_setup.c
@@ -0,0 +1,216 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <apn806_setup.h>
+#include <rfu.h>
+#include <ccu.h>
+#include <mci.h>
+#include <cache_llc.h>
+#include <debug.h>
+
+#define SMMU_sACR (MVEBU_SMMU_BASE + 0x10)
+#define SMMU_sACR_PG_64K (1 << 16)
+
+#define CCU_GSPMU_CR (MVEBU_CCU_BASE + 0x3F0)
+#define GSPMU_CPU_CONTROL (0x1 << 0)
+
+#define CCU_HTC_CR (MVEBU_CCU_BASE + 0x200)
+#define CCU_SET_POC_OFFSET 5
+
+#define CCU_LTC_CR (MVEBU_CCU_BASE + 0x300)
+#define CCU_CLEAN_INV_WRITE_OFFSET 8
+
+/* Secure MoChi incoming access */
+#define SEC_MOCHI_IN_ACC_REG (MVEBU_RFU_BASE + 0x4738)
+#define SEC_MOCHI_IN_ACC_IHB0_EN (1)
+#define SEC_MOCHI_IN_ACC_IHB1_EN (1 << 3)
+#define SEC_MOCHI_IN_ACC_IHB2_EN (1 << 6)
+#define SEC_MOCHI_IN_ACC_PIDI_EN (1 << 9)
+#define SEC_IN_ACCESS_ENA_ALL_MASTERS (SEC_MOCHI_IN_ACC_IHB0_EN | \
+ SEC_MOCHI_IN_ACC_IHB1_EN | \
+ SEC_MOCHI_IN_ACC_IHB2_EN | \
+ SEC_MOCHI_IN_ACC_PIDI_EN)
+
+/* Misc SoC configurations Base*/
+#define MVEBU_MISC_SOC_BASE (MVEBU_REGS_BASE + 0x6F4300)
+
+/* SYSRST_OUTn Config definitions */
+#define MVEBU_SYSRST_OUT_CONFIG_REG (MVEBU_MISC_SOC_BASE + 0x4)
+#define WD_MASK_SYS_RST_OUT (1 << 2)
+
+/*
+ * AXI Configuration.
+ */
+
+/* Used for Units of AP-806 (e.g. SDIO and etc) */
+#define MVEBU_AXI_ATTR_BASE (MVEBU_REGS_BASE + 0x6F4580)
+#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + 0x4 * index)
+
+enum axi_attr {
+ AXI_SDIO_ATTR = 0,
+ AXI_DFX_ATTR,
+ AXI_MAX_ATTR,
+};
+
+static void apn_sec_masters_access_en(uint32_t enable)
+{
+ uint32_t reg;
+
+ /* Open/Close incoming access for all masters.
+ The access is disabled in trusted boot mode
+ Could only be done in EL3
+ */
+ reg = mmio_read_32(SEC_MOCHI_IN_ACC_REG);
+ if (enable)
+ mmio_write_32(SEC_MOCHI_IN_ACC_REG, reg | SEC_IN_ACCESS_ENA_ALL_MASTERS);
+ else
+ mmio_write_32(SEC_MOCHI_IN_ACC_REG, reg & ~SEC_IN_ACCESS_ENA_ALL_MASTERS);
+}
+
+void setup_smmu(void)
+{
+ uint32_t reg;
+
+ /* Set the SMMU page size to 64 KB */
+ reg = mmio_read_32(SMMU_sACR);
+ reg |= SMMU_sACR_PG_64K;
+ mmio_write_32(SMMU_sACR, reg);
+}
+
+void init_aurora2(void)
+{
+ uint32_t reg;
+
+ /* Enable GSPMU control by CPU */
+ reg = mmio_read_32(CCU_GSPMU_CR);
+ reg |= GSPMU_CPU_CONTROL;
+ mmio_write_32(CCU_GSPMU_CR, reg);
+
+#if !LLC_DISABLE
+ /* Enable LLC in exclusive mode */
+ llc_enable(1);
+
+ /* Set point of coherency to DDR.
+ This is required by units which have
+ SW cache coherency */
+ reg = mmio_read_32(CCU_HTC_CR);
+ reg |= (0x1 << CCU_SET_POC_OFFSET);
+ mmio_write_32(CCU_HTC_CR, reg);
+
+ /* A0 Only: cache line clean & invalidate instead of)
+ ** cache line invalidate only - to avoid system hang
+ ** due to memory coherency issue */
+ if (apn806_rev_id_get() == APN806_REV_ID_A0) {
+ reg = mmio_read_32(CCU_LTC_CR);
+ reg |= (0x1 << CCU_CLEAN_INV_WRITE_OFFSET);
+ mmio_write_32(CCU_LTC_CR, reg);
+ }
+#endif /* !LLC_DISABLE */
+}
+
+void apn806_axi_attr_init(void)
+{
+ uint32_t index, data;
+
+ /* Initialize AXI attributes for APN806 */
+
+ /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */
+ for (index = 0; index < AXI_MAX_ATTR; index++) {
+ switch (index) {
+ /* DFX works with no coherent only -
+ there's no option to configure the Ax-Cache and Ax-Domain */
+ case AXI_DFX_ATTR:
+ continue;
+ default:
+ /* Set Ax-Cache as cacheable, no allocate, modifiable, bufferable
+ The values are different because Read & Write definition
+ is different in Ax-Cache */
+ data = mmio_read_32(MVEBU_AXI_ATTR_REG(index));
+ data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK;
+ data |= (CACHE_ATTR_WRITE_ALLOC | CACHE_ATTR_CACHEABLE | CACHE_ATTR_BUFFERABLE)
+ << MVEBU_AXI_ATTR_ARCACHE_OFFSET;
+ data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK;
+ data |= (CACHE_ATTR_READ_ALLOC | CACHE_ATTR_CACHEABLE | CACHE_ATTR_BUFFERABLE)
+ << MVEBU_AXI_ATTR_AWCACHE_OFFSET;
+ /* Set Ax-Domain as Outer domain */
+ data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK;
+ data |= DOMAIN_OUTER_SHAREABLE << MVEBU_AXI_ATTR_ARDOMAIN_OFFSET;
+ data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK;
+ data |= DOMAIN_OUTER_SHAREABLE << MVEBU_AXI_ATTR_AWDOMAIN_OFFSET;
+ mmio_write_32(MVEBU_AXI_ATTR_REG(index), data);
+ }
+ }
+
+ return;
+}
+
+void misc_soc_configurations(void)
+{
+ uint32_t reg;
+
+ /* Un-mask Watchdog reset from influencing the SYSRST_OUTn.
+ * Otherwise, upon WD timeout, the WD reset singal won't trigger reset
+ */
+ reg = mmio_read_32(MVEBU_SYSRST_OUT_CONFIG_REG);
+ reg &= ~(WD_MASK_SYS_RST_OUT);
+ mmio_write_32(MVEBU_SYSRST_OUT_CONFIG_REG, reg);
+}
+
+void apn806_init(void)
+{
+ /* Setup Aurora2. */
+ init_aurora2();
+
+ /* configure MCI mapping */
+ mci_remap_indirect_access_base();
+
+ /* configure RFU windows */
+ init_rfu();
+
+ /* configure CCU windows */
+ init_ccu();
+
+ /* configure the SMMU */
+ setup_smmu();
+
+ /* Open APN incoming access for all masters */
+ apn_sec_masters_access_en(1);
+
+ /* configure axi for APN*/
+ apn806_axi_attr_init();
+
+ /* misc configuration of the SoC */
+ misc_soc_configurations();
+}
diff --git a/drivers/marvell/mochi/cp110_setup.c b/drivers/marvell/mochi/cp110_setup.c
new file mode 100644
index 00000000..5538a588
--- /dev/null
+++ b/drivers/marvell/mochi/cp110_setup.c
@@ -0,0 +1,400 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <apn806_setup.h>
+#include <amb_adec.h>
+#include <iob.h>
+#include <icu.h>
+#include <mmio.h>
+
+/*
+ ICU configuration
+ */
+/* Multi instance sources, multipllied in dual CP mode */
+static const struct icu_irq irq_map_ns_multi[] = {
+ {22, 0, 0}, /* PCIx4 INT A interrupt */
+ {23, 1, 0}, /* PCIx1 INT A interrupt */
+ {24, 2, 0}, /* PCIx1 INT A interrupt */
+
+ {33, 3, 0}, /* PPv2 DBG AXI monitor */
+ {34, 3, 0}, /* HB1 AXI monitor */
+ {35, 3, 0}, /* AP AXI monitor */
+ {36, 3, 0}, /* PPv2 AXI monitor */
+
+ {38, 4, 0}, /* PPv2 Misc */
+
+ {39, 5, 0}, /* PPv2 irq */
+ {40, 6, 0}, /* PPv2 irq */
+ {41, 7, 0}, /* PPv2 irq */
+ {42, 8, 0}, /* PPv2 irq */
+ {43, 9, 0}, /* PPv2 irq */
+ {44, 10, 0}, /* PPv2 irq */
+ {45, 11, 0}, /* PPv2 irq */
+ {46, 12, 0}, /* PPv2 irq */
+ {47, 13, 0}, /* PPv2 irq */
+ {48, 14, 0}, /* PPv2 irq */
+ {49, 15, 0}, /* PPv2 irq */
+ {50, 16, 0}, /* PPv2 irq */
+ {51, 17, 0}, /* PPv2 irq */
+ {52, 18, 0}, /* PPv2 irq */
+ {53, 19, 0}, /* PPv2 irq */
+ {54, 20, 0}, /* PPv2 irq */
+
+ {78, 21, 0}, /* MG irq */
+ {88, 22, 0}, /* EIP-197 ring-0 */
+ {89, 23, 0}, /* EIP-197 ring-1 */
+ {90, 24, 0}, /* EIP-197 ring-2 */
+ {91, 25, 0}, /* EIP-197 ring-3 */
+ {92, 26, 0}, /* EIP-197 int */
+ {95, 27, 0}, /* EIP-150 irq */
+ {102, 28, 0}, /* USB3 Device irq */
+ {105, 29, 0}, /* USB3 Host-1 irq */
+ {106, 30, 0}, /* USB3 Host-0 irq */
+ {107, 31, 0}, /* SATA Host-1 irq */
+ {109, 31, 0}, /* SATA Host-0 irq */
+ {126, 33, 0}, /* PTP irq */
+ {127, 34, 0}, /* GOP-3 irq */
+ {128, 35, 0}, /* GOP-2 irq */
+ {129, 36, 0}, /* GOP-0 irq */
+
+ /* PPv2 interrupts which originally assigned as single interrupts.
+ * To avoid updating Device tree, left original SPI assignment 60-63,
+ * hence there is a gap between previous multi interrupts */
+ {55, 60, 0}, /* PPv2 irq */
+ {56, 61, 0}, /* PPv2 irq */
+ {57, 62, 0}, /* PPv2 irq */
+ {58, 63, 0}, /* PPv2 irq */
+};
+
+/* Single instance sources, not multiplies in dual CP mode */
+static const struct icu_irq irq_map_ns_single[] = {
+ {27, 37, 0}, /* SD/MMC */
+ {76, 38, 0}, /* Audio */
+ {77, 39, 0}, /* MSS RTC */
+ {79, 40, 0}, /* GPIO 56-63 */
+ {80, 41, 0}, /* GPIO 48-55 */
+ {81, 42, 0}, /* GPIO 40-47 */
+ {82, 43, 0}, /* GPIO 32-39 */
+ {83, 44, 0}, /* GPIO 24-31 */
+ {84, 45, 0}, /* GPIO 16-23 */
+ {85, 46, 0}, /* GPIO 8-15 */
+ {86, 47, 0}, /* GPIO 0-7 */
+ {111, 48, 0}, /* TDM-MC func 1 */
+ {112, 49, 0}, /* TDM-MC func 0 */
+ {113, 50, 0}, /* TDM-MC irq */
+ {115, 51, 0}, /* NAND irq */
+ {117, 52, 0}, /* SPI-1 irq */
+ {118, 53, 0}, /* SPI-0 irq */
+ {120, 54, 0}, /* I2C 0 irq */
+ {121, 55, 0}, /* I2C 1 irq */
+ {122, 56, 0}, /* UART 0 irq */
+ {123, 57, 0}, /* UART 1 irq */
+ {124, 58, 0}, /* UART 2 irq */
+ {125, 59, 0}, /* UART 3 irq */
+};
+
+/* SEI - System Error Interrupts */
+/* Note: SPI ID 0-20 are reserved for North-Bridge */
+static struct icu_irq irq_map_sei[] = {
+ {11, 21, 0}, /* SEI error CP-2-CP */
+ {15, 22, 0}, /* PIDI-64 SOC */
+ {16, 23, 0}, /* D2D error irq */
+ {17, 24, 0}, /* D2D irq */
+ {18, 25, 0}, /* NAND error */
+ {19, 26, 0}, /* PCIx4 error */
+ {20, 27, 0}, /* PCIx1_0 error */
+ {21, 28, 0}, /* PCIx1_1 error */
+ {25, 29, 0}, /* SDIO reg error */
+ {75, 30, 0}, /* IOB error */
+ {94, 31, 0}, /* EIP150 error */
+ {97, 32, 0}, /* XOR-1 system error */
+ {99, 33, 0}, /* XOR-0 system error */
+ {108, 34, 0}, /* SATA-1 error */
+ {110, 35, 0}, /* SATA-0 error */
+ {114, 36, 0}, /* TDM-MC error */
+ {116, 37, 0}, /* DFX server irq */
+ {117, 38, 0}, /* Device bus error */
+ {147, 39, 0}, /* Audio error */
+ {171, 40, 0}, /* PIDI Sync error */
+};
+
+/* REI - RAM Error Interrupts */
+static const struct icu_irq irq_map_rei[] = {
+ {12, 0, 0}, /* REI error CP-2-CP */
+ {26, 1, 0}, /* SDIO memory error */
+ {87, 2, 0}, /* EIP-197 ECC error */
+ {93, 3, 1}, /* EIP-150 RAM error */
+ {96, 4, 0}, /* XOR-1 memory irq */
+ {98, 5, 0}, /* XOR-0 memory irq */
+ {100, 6, 1}, /* USB3 device tx parity */
+ {101, 7, 1}, /* USB3 device rq parity */
+ {103, 8, 1}, /* USB3H-1 RAM error */
+ {104, 9, 1}, /* USB3H-0 RAM error */
+};
+
+static const struct icu_config icu_config = {
+ .ns_multi = { irq_map_ns_multi, ARRAY_SIZE(irq_map_ns_multi) },
+ .ns_single = { irq_map_ns_single, ARRAY_SIZE(irq_map_ns_single) },
+ .sei = { irq_map_sei, ARRAY_SIZE(irq_map_sei) },
+ .rei = { irq_map_rei, ARRAY_SIZE(irq_map_rei) },
+};
+
+/*
+ * AXI Configuration.
+ */
+
+ /* Used for Units of CP-110 (e.g. USB device, USB Host, and etc) */
+#define MVEBU_AXI_ATTR_BASE(cp_index) (MVEBU_CP_REGS_BASE(cp_index) + 0x441300)
+#define MVEBU_AXI_ATTR_REG(cp_index, index) (MVEBU_AXI_ATTR_BASE(cp_index) + 0x4 * index)
+
+/* AXI Protection bits */
+#define MVEBU_AXI_PROT_BASE(cp_index) (MVEBU_CP_REGS_BASE(cp_index) + 0x441200)
+
+/* AXI Protection regs for A0 revision */
+#define MVEBU_AXI_PROT_REG_A0(cp_index, index) ((index <= 6) ? (MVEBU_AXI_PROT_BASE(cp_index) + 0x4 * index) : \
+ (MVEBU_AXI_PROT_BASE(cp_index) + 0x20 + 0x4 * (index - 7)))
+#define MVEBU_AXI_PROT_REGS_NUM_A0 (9)
+
+/* AXI Protection regs for A1 revision */
+#define MVEBU_AXI_PROT_REG(cp_index, index) ((index <= 4) ? (MVEBU_AXI_PROT_BASE(cp_index) + 0x4 * index) : \
+ (MVEBU_AXI_PROT_BASE(cp_index) + 0x18))
+#define MVEBU_AXI_PROT_REGS_NUM (6)
+
+#define MVEBU_SOC_CFGS_BASE(cp_index) (MVEBU_CP_REGS_BASE(cp_index) + 0x441900)
+#define MVEBU_SOC_CFG_REG(cp_index, index) (MVEBU_SOC_CFGS_BASE(cp_index) + 0x4 * index)
+#define MVEBU_SOC_CFG_REG_NUM (0)
+#define MVEBU_SOC_CFG_GLOG_SECURE_EN_MASK (0xE)
+
+/* SATA3 MBUS to AXI regs */
+#define MVEBU_SATA_M2A_AXI_PORT_CTRL_REG(cp_index) (MVEBU_CP_REGS_BASE(cp_index) + 0x54ff04)
+
+/* AXI to MBUS bridge registers */
+#define MVEBU_AMB_IP_BRIDGE_WIN_REG(cp_index, win) (MVEBU_AMB_IP_BASE(cp_index) + (win * 0x8))
+#define MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET 0
+#define MVEBU_AMB_IP_BRIDGE_WIN_EN_MASK (0x1 << MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET)
+#define MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET 16
+#define MVEBU_AMB_IP_BRIDGE_WIN_SIZE_MASK (0xffff << MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET)
+
+enum axi_attr {
+ AXI_ADUNIT_ATTR = 0,
+ AXI_COMUNIT_ATTR,
+ AXI_EIP197_ATTR,
+ AXI_USB3D_ATTR,
+ AXI_USB3H0_ATTR,
+ AXI_USB3H1_ATTR,
+ AXI_SATA0_ATTR,
+ AXI_SATA1_ATTR,
+ AXI_DAP_ATTR,
+ AXI_DFX_ATTR,
+ AXI_DBG_TRC_ATTR = 12,
+ AXI_SDIO_ATTR,
+ AXI_MSS_ATTR,
+ AXI_MAX_ATTR,
+};
+
+/* Most stream IDS are configured centrally in the CP-110 RFU
+ * but some are configured inside the unit registers
+ */
+#define RFU_STREAM_ID_BASE (0x450000)
+#define AUDIO_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x0)
+#define TDM_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x4)
+#define USB3D_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x8)
+#define USB3H_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0xC)
+#define USB3H_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x10)
+#define SATA_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x14)
+#define SATA_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x18)
+#define DBG_TRC_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x24)
+#define SDIO_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x28)
+#define DAP_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x2C)
+
+#define CP_DMA_0_STREAM_ID_REG (0x6B0010)
+#define CP_DMA_1_STREAM_ID_REG (0x6D0010)
+
+/* We allocate IDs 0-127 for PCI since
+ * SR-IOV devices can generate many functions
+ * that need a unique Stream-ID.
+ */
+#define MAX_PCIE_STREAM_ID (0x80)
+
+uintptr_t stream_id_reg[] = {
+ AUDIO_STREAM_ID_REG,
+ TDM_STREAM_ID_REG,
+ USB3D_STREAM_ID_REG,
+ USB3H_0_STREAM_ID_REG,
+ USB3H_1_STREAM_ID_REG,
+ SATA_0_STREAM_ID_REG,
+ SATA_1_STREAM_ID_REG,
+ DBG_TRC_STREAM_ID_REG,
+ SDIO_STREAM_ID_REG,
+ DAP_STREAM_ID_REG,
+ CP_DMA_0_STREAM_ID_REG,
+ CP_DMA_1_STREAM_ID_REG,
+ 0
+};
+
+void cp110_errata_wa_init(int cp_index)
+{
+ uint32_t data;
+
+ /* ERRATA GL-4076863 (STORM-916):
+ * Reset value for global_secure_enable inputs must be changed from '1' to '0'.
+ * When asserted, only "secured" transactions can enter IHB configuration space.
+ * However, blocking AXI transactions is performed by IOB.
+ * Performing it also at IHB/HB complicates programming model.
+ *
+ * Enable non-secure access in SOC configuration register */
+ data = mmio_read_32(MVEBU_SOC_CFG_REG(cp_index, MVEBU_SOC_CFG_REG_NUM));
+ data &= ~MVEBU_SOC_CFG_GLOG_SECURE_EN_MASK;
+ mmio_write_32(MVEBU_SOC_CFG_REG(cp_index, MVEBU_SOC_CFG_REG_NUM), data);
+}
+
+/* Set a unique stream id for all DMA capable devices */
+void cp110_stream_id_init(uintptr_t cp110_base)
+{
+ int i = 0;
+ uint32_t stream_id = MAX_PCIE_STREAM_ID;
+
+ while (stream_id_reg[i]) {
+ /* SATA port 0/1 are in the same SATA unit, and they should use
+ ** the same STREAM ID number */
+ if (stream_id_reg[i] == SATA_0_STREAM_ID_REG)
+ mmio_write_32(cp110_base + stream_id_reg[i++], stream_id);
+ else
+ mmio_write_32(cp110_base + stream_id_reg[i++], stream_id++);
+ }
+}
+
+void cp110_axi_attr_init(int cp_index)
+{
+ uint32_t index, data;
+
+ /* Initialize AXI attributes for Armada-7K/8K SoC */
+
+ /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */
+ for (index = 0; index < AXI_MAX_ATTR; index++) {
+ switch (index) {
+ /* DFX and MSS unit works with no coherent only -
+ there's no option to configure the Ax-Cache and Ax-Domain */
+ case AXI_DFX_ATTR:
+ case AXI_MSS_ATTR:
+ continue;
+ default:
+ /* Set Ax-Cache as cacheable, no allocate, modifiable, bufferable
+ The values are different because Read & Write definition
+ is different in Ax-Cache */
+ data = mmio_read_32(MVEBU_AXI_ATTR_REG(cp_index, index));
+ data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK;
+ data |= (CACHE_ATTR_WRITE_ALLOC | CACHE_ATTR_CACHEABLE | CACHE_ATTR_BUFFERABLE)
+ << MVEBU_AXI_ATTR_ARCACHE_OFFSET;
+ data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK;
+ data |= (CACHE_ATTR_READ_ALLOC | CACHE_ATTR_CACHEABLE | CACHE_ATTR_BUFFERABLE)
+ << MVEBU_AXI_ATTR_AWCACHE_OFFSET;
+ /* Set Ax-Domain as Outer domain */
+ data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK;
+ data |= DOMAIN_OUTER_SHAREABLE << MVEBU_AXI_ATTR_ARDOMAIN_OFFSET;
+ data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK;
+ data |= DOMAIN_OUTER_SHAREABLE << MVEBU_AXI_ATTR_AWDOMAIN_OFFSET;
+ mmio_write_32(MVEBU_AXI_ATTR_REG(cp_index, index), data);
+ }
+ }
+
+ if (apn806_rev_id_get() == APN806_REV_ID_A1) {
+ /* SATA IOCC supported in A1 rev only:
+ * Cache attributes for SATA MBUS to AXI configuration */
+ data = mmio_read_32(MVEBU_SATA_M2A_AXI_PORT_CTRL_REG(cp_index));
+ data &= ~MVEBU_SATA_M2A_AXI_AWCACHE_MASK;
+ data |= (CACHE_ATTR_WRITE_ALLOC | CACHE_ATTR_CACHEABLE | CACHE_ATTR_BUFFERABLE)
+ << MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET;
+ data &= ~MVEBU_SATA_M2A_AXI_ARCACHE_MASK;
+ data |= (CACHE_ATTR_READ_ALLOC | CACHE_ATTR_CACHEABLE | CACHE_ATTR_BUFFERABLE)
+ << MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET;
+ mmio_write_32(MVEBU_SATA_M2A_AXI_PORT_CTRL_REG(cp_index), data);
+
+ /* Set all IO's AXI attribute to non-secure access. */
+ for (index = 0; index < MVEBU_AXI_PROT_REGS_NUM; index++)
+ mmio_write_32(MVEBU_AXI_PROT_REG(cp_index, index), DOMAIN_SYSTEM_SHAREABLE);
+ } else {
+ /* for A0 rev only set AXI attribute to non-secure access
+ * (different AXI_PROT reg mapping vs A1) */
+ for (index = 0; index < MVEBU_AXI_PROT_REGS_NUM_A0; index++)
+ mmio_write_32(MVEBU_AXI_PROT_REG_A0(cp_index, index), DOMAIN_SYSTEM_SHAREABLE);
+ }
+
+ return;
+}
+
+void amb_bridge_init(int cp_index)
+{
+ uint32_t reg;
+
+ /* Open AMB bridge Window to Access COMPHY/MDIO registers */
+ reg = mmio_read_32(MVEBU_AMB_IP_BRIDGE_WIN_REG(cp_index, 0));
+ reg &= ~(MVEBU_AMB_IP_BRIDGE_WIN_SIZE_MASK | MVEBU_AMB_IP_BRIDGE_WIN_EN_MASK);
+ reg |= (0x7ff << MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET | 0x1 << MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET);
+ mmio_write_32(MVEBU_AMB_IP_BRIDGE_WIN_REG(cp_index, 0), reg);
+}
+
+void cp110_init(int cp_index)
+{
+ /* configure AXI-MBUS windows for CP0*/
+ init_amb_adec(cp_index);
+
+ /* configure IOB windows for CP0*/
+ init_iob(cp_index);
+
+ /* configure axi for CP0*/
+ cp110_axi_attr_init(cp_index);
+
+ /* Execute SW WA for erratas */
+ cp110_errata_wa_init(cp_index);
+
+ /* configure icu for CP0 */
+ /* ICU - Interrupt Consolidation unit
+ * CP0: interrupt 0..63 mapped to ID 64..127 in AP
+ * CP1: interrupt 64..127 mapped to ID 288..351 in AP */
+ icu_init(cp_index, 0, cp_index * 64, &icu_config);
+
+ /* configure stream id for CP0 */
+ cp110_stream_id_init(MVEBU_CP_REGS_BASE(cp_index));
+
+ /* Open AMB bridge for comphy for CP0 & CP1*/
+ amb_bridge_init(cp_index);
+}
+
+/* Do the minimal setup required to configure the CP in BLE */
+void cp110_ble_init(int cp_index)
+{
+ amb_bridge_init(cp_index);
+}
diff --git a/drivers/marvell/pci_ep.h b/drivers/marvell/pci_ep.h
new file mode 100644
index 00000000..55882026
--- /dev/null
+++ b/drivers/marvell/pci_ep.h
@@ -0,0 +1,59 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _PCIE_EP_H_
+#define _PCIE_EP_H_
+
+#define PCIE_MAX_BARS 6
+#define PCIE_MAX_LANES 16
+
+struct pci_hw_cfg {
+ uint8_t delay_cfg;
+ uint8_t master_en;
+ uint8_t lane_width;
+ uint8_t lane_ids[PCIE_MAX_LANES];
+ uint8_t clk_src;
+ uint8_t clk_out;
+ uint8_t is_end_point;
+ uintptr_t mac_base;
+ uintptr_t comphy_base;
+ uintptr_t hpipe_base;
+ uintptr_t dfx_base;
+};
+
+void dw_pcie_ep_init(uintptr_t dw_base, uint8_t delay_cfg, uint8_t master_en);
+int comphy_pcie_power_up(uint32_t lane, struct pci_hw_cfg *hw);
+
+#endif /* _PCIE_EP_H_ */
+
diff --git a/drivers/marvell/pcie-comphy-cp110.c b/drivers/marvell/pcie-comphy-cp110.c
new file mode 100644
index 00000000..cdfb8876
--- /dev/null
+++ b/drivers/marvell/pcie-comphy-cp110.c
@@ -0,0 +1,418 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <mmio.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include "comphy.h"
+#include "pci_ep.h"
+
+#define SD_ADDR(base, lane) (base + 0x1000 * lane)
+#define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800)
+#define COMPHY_ADDR(base, lane) (base + 0x28 * lane)
+
+
+void reg_set(uintptr_t addr, uint32_t data, uint32_t mask)
+{
+ uint32_t reg_data;
+ reg_data = mmio_read_32(addr);
+ reg_data &= ~mask;
+ reg_data |= data;
+ mmio_write_32(addr, reg_data);
+}
+
+uint32_t polling_with_timeout(uintptr_t addr, uint32_t val, uint32_t mask, unsigned long usec_timout)
+{
+ uint32_t data;
+
+ do {
+ udelay(1);
+ data = mmio_read_32(addr) & mask;
+ } while (data != val && --usec_timout > 0);
+
+ if (usec_timout == 0)
+ return data;
+ return 0;
+}
+
+void comphy_mux_set_pcie(uintptr_t comphy_addr, int lane)
+{
+ uint32_t val, mask;
+
+ /* Set the PIPE as PCIe Gen3 */
+ mask = 0xF << (4 * lane);
+ val = 0x4 << (4 * lane);
+ reg_set(comphy_addr + COMMON_SELECTOR_PIPE_OFFSET, val, mask);
+
+ /* Disconnect the Ethernet PHYs */
+ mask = 0xF << (4 * lane);
+ val = 0;
+ reg_set(comphy_addr + COMMON_SELECTOR_PHY_OFFSET, val, mask);
+}
+
+int comphy_pcie_power_up(uint32_t lane, struct pci_hw_cfg *hw)
+{
+ uint32_t mask, data, ret = 1;
+ uintptr_t hpipe_addr = HPIPE_ADDR(hw->hpipe_base, lane);
+ uintptr_t comphy_addr = COMPHY_ADDR(hw->comphy_base, lane);
+ uintptr_t addr;
+
+ printf("Setting up Comphy lane %d as PCIe\n", lane);
+
+ INFO("PCIe clock = %x\n", hw->clk_out);
+ INFO("PCIe RC = %d\n", !hw->is_end_point);
+ INFO("PCIe Width = %d\n", hw->lane_width);
+
+ comphy_mux_set_pcie(comphy_addr, lane);
+
+ /* enable PCIe by4 and by2 */
+ if (lane == 0) {
+ if (hw->lane_width == 4) {
+ reg_set(hw->comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET, COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK);
+ } else if (hw->lane_width == 2) {
+ reg_set(hw->comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET, COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK);
+ }
+ }
+
+ /* if PCIe clock is output and clock source from SerDes lane 5, need to configure the clock-source MUX.
+ ** By default, the clock source is from lane 4 */
+ if (hw->clk_out && hw->clk_src && (lane == 5))
+ reg_set(hw->dfx_base + DFX_DEV_GEN_CTRL12, 0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET,
+ DFX_DEV_GEN_PCIE_CLK_SRC_MASK);
+
+ INFO("stage: RFU configurations - hard reset comphy\n");
+ /* RFU configurations - hard reset comphy */
+ mask = COMMON_PHY_CFG1_PWR_UP_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
+ mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
+ data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
+ mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
+ mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
+ mask |= COMMON_PHY_PHY_MODE_MASK;
+ data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* release from hard reset */
+ mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
+ mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
+ data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* Wait 1ms - until band gap and ref clock ready */
+ mdelay(1);
+ /* Start comphy Configuration */
+ INFO("stage: Comphy configuration\n");
+ /* Set PIPE soft reset */
+ mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
+ data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
+ /* Set PHY datapath width mode for V0 */
+ mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
+ data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
+ /* Set Data bus width USB mode for V0 */
+ mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
+ data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
+ /* Set CORE_CLK output frequency for 250Mhz */
+ mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
+ data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
+ /* Set PLL ready delay for 0x2 */
+ data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET;
+ mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK;
+ if (hw->lane_width != 1) {
+ data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET;
+ mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK;
+ data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET;
+ mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK;
+ }
+ reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask);
+
+ /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */
+ data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET;
+ mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK;
+ if (hw->lane_width != 1) {
+ mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK;
+ mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK;
+ mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK;
+ if (lane == 0) {
+ data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET;
+ data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET;
+ } else if (lane == (hw->lane_width - 1)) {
+ data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET;
+ }
+ }
+ reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask);
+ /* Config update polarity equalization */
+ reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG,
+ 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET, HPIPE_CFG_UPDATE_POLARITY_MASK);
+ /* Set PIPE version 4 to mode enable */
+ reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG,
+ 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET, HPIPE_DFE_CTRL_28_PIPE4_MASK);
+ /* TODO: check if pcie clock is output/input - for bringup use input*/
+ /* Enable PIN clock 100M_125M */
+ mask = 0;
+ data = 0;
+ /* Only if clock is output, configure the clock-source mux */
+ if (hw->clk_out) {
+ mask |= HPIPE_MISC_CLK100M_125M_MASK;
+ data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET;
+ }
+ /* Set PIN_TXDCLK_2X Clock Frequency Selection for outputs 500MHz clock */
+ mask |= HPIPE_MISC_TXDCLK_2X_MASK;
+ data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET;
+ /* Enable 500MHz Clock */
+ mask |= HPIPE_MISC_CLK500_EN_MASK;
+ data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET;
+ if (hw->clk_out) { /* output */
+ /* Set reference clock comes from group 1 */
+ mask |= HPIPE_MISC_REFCLK_SEL_MASK;
+ data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
+ } else {
+ /* Set reference clock comes from group 2 */
+ mask |= HPIPE_MISC_REFCLK_SEL_MASK;
+ data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET;
+ }
+ reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
+ if (hw->clk_out) { /* output */
+ /* Set reference frequcency select - 0x2 for 25MHz*/
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ } else {
+ /* Set reference frequcency select - 0x0 for 100MHz*/
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ }
+ /* Set PHY mode to PCIe */
+ mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
+ data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
+
+ /* ref clock alignment */
+ if (hw->lane_width != 1) {
+ mask = HPIPE_LANE_ALIGN_OFF_MASK;
+ data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET;
+ reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask);
+ }
+
+ /* Set the amount of time spent in the LoZ state - set for 0x7 only if
+ the PCIe clock is output */
+ if (hw->clk_out)
+ reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
+ 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
+
+ /* Set Maximal PHY Generation Setting(8Gbps) */
+ mask = HPIPE_INTERFACE_GEN_MAX_MASK;
+ data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET;
+ /* Set Link Train Mode (Tx training control pins are used) */
+ mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK;
+ data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask);
+
+ /* Set Idle_sync enable */
+ mask = HPIPE_PCIE_IDLE_SYNC_MASK;
+ data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET;
+ /* Select bits for PCIE Gen3(32bit) */
+ mask |= HPIPE_PCIE_SEL_BITS_MASK;
+ data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask);
+
+ /* Enable Tx_adapt_g1 */
+ mask = HPIPE_TX_TRAIN_CTRL_G1_MASK;
+ data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET;
+ /* Enable Tx_adapt_gn1 */
+ mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK;
+ data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET;
+ /* Disable Tx_adapt_g0 */
+ mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK;
+ data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
+
+ /* Set reg_tx_train_chk_init */
+ mask = HPIPE_TX_TRAIN_CHK_INIT_MASK;
+ data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET;
+ /* Enable TX_COE_FM_PIN_PCIE3_EN */
+ mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK;
+ data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
+
+ INFO("stage: TRx training parameters\n");
+ /* Set Preset sweep configurations */
+ mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK;
+ data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET;
+
+ mask |= HPIPE_TX_NUM_OF_PRESET_MASK;
+ data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET;
+
+ mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK;
+ data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask);
+
+ /* Tx train start configuration */
+ mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK;
+ data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET;
+
+ mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK;
+ data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET;
+
+ mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK;
+ data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET;
+
+ mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK;
+ data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
+
+ /* Enable Tx train P2P */
+ mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
+ data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
+
+ /* Configure Tx train timeout */
+ mask = HPIPE_TRX_TRAIN_TIMER_MASK;
+ data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask);
+
+ /* Disable G0/G1/GN1 adaptation */
+ mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK
+ | HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
+ data = 0;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
+
+ /* Disable DTL frequency loop */
+ mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
+ data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
+
+ /* Configure G3 DFE */
+ mask = HPIPE_G3_DFE_RES_MASK;
+ data = 0x3 << HPIPE_G3_DFE_RES_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
+
+ /* Force DFE resolution (use GEN table value) */
+ mask = HPIPE_DFE_RES_FORCE_MASK;
+ data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
+
+ /* Configure initial and final coefficient value for receiver */
+ mask = HPIPE_G3_RX_SELMUPI_MASK;
+ data = 0x1 << HPIPE_G3_RX_SELMUPI_OFFSET;
+
+ mask |= HPIPE_G3_RX_SELMUPF_MASK;
+ data |= 0x1 << HPIPE_G3_RX_SELMUPF_OFFSET;
+
+ mask |= HPIPE_G3_SETTING_BIT_MASK;
+ data |= 0x0 << HPIPE_G3_SETTING_BIT_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G3_SETTINGS_1_REG, data, mask);
+
+ /* Trigger sampler enable pulse */
+ mask = HPIPE_SMAPLER_MASK;
+ data = 0x1 << HPIPE_SMAPLER_OFFSET;
+ reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
+ udelay(5);
+ reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask);
+
+ /* FFE resistor tuning for different bandwidth */
+ mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
+ data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
+
+ mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
+ data |= 0x1 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
+
+ if (!hw->is_end_point) {
+ /* Set phy in root complex mode */
+ mask = HPIPE_CFG_PHY_RC_EP_MASK;
+ data = 0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET;
+ reg_set(hpipe_addr + HPIPE_LANE_EQU_CONFIG_0_REG, data, mask);
+ }
+
+ INFO("stage: Comphy power up\n");
+
+ /* for PCIe by4 or by2 - release from reset only after finish to configure all lanes */
+ if ((hw->lane_width == 1) || (lane == (hw->lane_width - 1))) {
+ uint32_t i, start_lane, end_lane;
+
+ if (hw->lane_width != 1) {
+ /* allows writing to all lanes in one write */
+ reg_set(hw->comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x0 << COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET,
+ COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK);
+ start_lane = 0;
+ end_lane = hw->lane_width;
+
+ /* Release from PIPE soft reset
+ for PCIe by4 or by2 - release from soft reset all lanes - can't use
+ read modify write */
+ reg_set(HPIPE_ADDR(hw->hpipe_base, 0) + HPIPE_RST_CLK_CTRL_REG,
+ 0x24, 0xffffffff);
+ } else {
+ start_lane = lane;
+ end_lane = lane + 1;
+
+ /* Release from PIPE soft reset
+ for PCIe by4 or by2 - release from soft reset all lanes */
+ reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
+ 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
+ }
+
+
+ if (hw->lane_width != 1) {
+ /* disable writing to all lanes with one write */
+ reg_set(hw->comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x3210 << COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET,
+ COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK);
+ }
+
+ INFO("stage: Check PLL\n");
+ /* Read lane status */
+ for (i = start_lane; i < end_lane; i++) {
+ addr = HPIPE_ADDR(hw->hpipe_base, i) + HPIPE_LANE_STATUS1_REG;
+ data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 15000);
+ if (data != 0) {
+ INFO("Read from reg = 0x%lx - value = 0x%x\n",
+ hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
+ ERROR("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
+ ret = 0;
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/drivers/marvell/rfu.c b/drivers/marvell/rfu.c
new file mode 100644
index 00000000..39b37395
--- /dev/null
+++ b/drivers/marvell/rfu.c
@@ -0,0 +1,197 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#include <plat_def.h>
+#include <debug.h>
+#include <mmio.h>
+#include <mvebu.h>
+#include <rfu.h>
+#include <plat_config.h>
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+#define DEBUG_ADDR_MAP
+#endif
+
+/* common defines */
+#define WIN_ENABLE_BIT (0x1)
+/* Physical address of the base of the window = {Addr[19:0],20`h0} */
+#define ADDRESS_SHIFT (20 - 4)
+#define ADDRESS_MASK (0xFFFFFFF0)
+#define RFU_WIN_ALIGNMENT_1M (0x100000)
+#define RFU_WIN_ALIGNMENT_64K (0x10000)
+
+/* AP registers */
+#define RFU_WIN_ALR_OFFSET(win) (rfu_base + 0x0 + (0x10 * win))
+#define RFU_WIN_AHR_OFFSET(win) (rfu_base + 0x8 + (0x10 * win))
+#define RFU_WIN_CR_OFFSET(win) (rfu_base + 0xC + (0x10 * win))
+#define RFU_GCR_OFFSET (rfu_base + 0x70)
+
+
+uintptr_t rfu_base;
+
+
+static void rfu_win_check(struct rfu_win *win, uint32_t win_num)
+{
+ uint64_t base_addr, win_size;
+ uint32_t alignment_value = RFU_WIN_ALIGNMENT_1M;
+
+ /* for RFU The base is always 1M aligned */
+ /* check if address is aligned to 1M */
+ base_addr = ((uint64_t)win->base_addr_high << 32) + win->base_addr_low;
+ if (IS_NOT_ALIGN(base_addr, RFU_WIN_ALIGNMENT_1M)) {
+ base_addr = ALIGN_UP(base_addr, RFU_WIN_ALIGNMENT_1M);
+ ERROR("Window %d: base address unaligned to 0x%x\n", win_num, RFU_WIN_ALIGNMENT_1M);
+ printf("Align up the base address to 0x%lx\n", base_addr);
+ win->base_addr_high = (uint32_t)(base_addr >> 32);
+ win->base_addr_low = (uint32_t)(base_addr);
+ }
+
+ /* size parameter validity check */
+ win_size = ((uint64_t)win->win_size_high << 32) + win->win_size_low;
+ if (IS_NOT_ALIGN(win_size, alignment_value)) {
+ win_size = ALIGN_UP(win_size, alignment_value);
+ ERROR("Window %d: window size unaligned to 0x%x\n", win_num, alignment_value);
+ printf("Aligning size to 0x%lx\n", win_size);
+ win->win_size_high = (uint32_t)(win_size >> 32);
+ win->win_size_low = (uint32_t)(win_size);
+ }
+}
+
+static void rfu_enable_win(struct rfu_win *win, uint32_t win_num)
+{
+ uint32_t alr, ahr;
+ uint64_t start_addr, end_addr;
+
+ if (win->target_id < 0 || win->target_id >= RFU_MAX_WIN_ID) {
+ ERROR("target ID = %d, is invalid\n", win->target_id);
+ return;
+ }
+
+ /* calculate 64bit start-address and end-address */
+ start_addr = ((uint64_t)win->base_addr_high << 32) + win->base_addr_low;
+ end_addr = (start_addr + (((uint64_t)win->win_size_high << 32) + win->win_size_low) - 1);
+
+ alr = (uint32_t)((start_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
+ alr |= WIN_ENABLE_BIT;
+ ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
+
+ /* write start address and end address for rfu window */
+ mmio_write_32(RFU_WIN_ALR_OFFSET(win_num), alr);
+ mmio_write_32(RFU_WIN_AHR_OFFSET(win_num), ahr);
+
+ /* write window target */
+ mmio_write_32(RFU_WIN_CR_OFFSET(win_num), win->target_id);
+}
+
+#ifdef DEBUG_ADDR_MAP
+static void dump_rfu(void)
+{
+ uint32_t trgt_id, win_id;
+ uint32_t alr, ahr;
+ uint64_t start, end;
+ char *rfu_target_name[RFU_MAX_TID] = {"MCI-0 ", "MCI-1 ", "MCI-2 ", "PIDI ",
+ "SPI ", "STM ", "BootRoom "};
+
+ /* Dump all RFU windows */
+ printf("bank target start end\n");
+ printf("----------------------------------------------------\n");
+ for (win_id = 0; win_id < RFU_MAX_WIN_ID; win_id++) {
+ alr = mmio_read_32(RFU_WIN_ALR_OFFSET(win_id));
+ if (alr & WIN_ENABLE_BIT) {
+ alr &= ~WIN_ENABLE_BIT;
+ /* in case this is BOOTROM window */
+ if (win_id == 0) {
+ ahr = alr;
+ trgt_id = BOOTROM_TID;
+ } else {
+ ahr = mmio_read_32(RFU_WIN_AHR_OFFSET(win_id));
+ trgt_id = mmio_read_32(RFU_WIN_CR_OFFSET(win_id));
+ }
+ start = ((uint64_t)alr << ADDRESS_SHIFT);
+ end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT);
+ printf("rfu %s 0x%016lx 0x%016lx\n", rfu_target_name[trgt_id], start, end);
+ }
+ }
+ printf("rfu PIDI-port - all other IO transactions\n");
+
+ return;
+}
+#endif
+
+int init_rfu(void)
+{
+ struct rfu_win *win;
+ uint32_t win_id, win_reg;
+ uint32_t win_count;
+
+ INFO("Initializing RFU Address decoding\n");
+
+ /* Get the base address of the address decoding MBUS */
+ rfu_base = marvell_get_rfu_reg_offs();
+
+ /* Get the array of the windows and its size */
+ marvell_get_rfu_memory_map(&win, &win_count);
+ if (win_count <= 0) {
+ INFO("no windows configurations found\n");
+ }
+ if (win_count > RFU_MAX_WIN_ID) {
+ INFO("number of windows is bigger than %d\n", RFU_MAX_WIN_ID);
+ return 0;
+ }
+
+ /* set the default target id to PIDI */
+ win_reg = PIDI_TID;
+ mmio_write_32(RFU_GCR_OFFSET, win_reg);
+
+ /* disable all RFU windows */
+ for (win_id = 0; win_id < RFU_MAX_WIN_ID; win_id++) {
+ win_reg = mmio_read_32(RFU_WIN_ALR_OFFSET(win_id));
+ win_reg &= ~WIN_ENABLE_BIT;
+ mmio_write_32(RFU_WIN_ALR_OFFSET(win_id), win_reg);
+ }
+
+ /* enable relevant windows, starting from win_id=1 because index 0 dedicated for BootRom */
+ for (win_id = 1; win_id <= win_count; win_id++, win++) {
+ rfu_win_check(win, win_id);
+ rfu_enable_win(win, win_id);
+ }
+
+#ifdef DEBUG_ADDR_MAP
+ dump_rfu();
+#endif
+
+ INFO("Done RFU Address decoding Initializing\n");
+
+ return 0;
+}
diff --git a/include/drivers/marvell/a8k_i2c.h b/include/drivers/marvell/a8k_i2c.h
new file mode 100644
index 00000000..22d1dac7
--- /dev/null
+++ b/include/drivers/marvell/a8k_i2c.h
@@ -0,0 +1,61 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _A8K_I2C_H_
+#define _A8K_I2C_H_
+
+/*
+ * Initialization, must be called once on start up, may be called
+ * repeatedly to change the speed and slave addresses.
+ */
+void i2c_init(void *i2c_base);
+
+/*
+ * Read/Write interface:
+ * chip: I2C chip address, range 0..127
+ * addr: Memory (register) address within the chip
+ * alen: Number of bytes to use for addr (typically 1, 2 for larger
+ * memories, 0 for register type devices with only one
+ * register)
+ * buffer: Where to read/write the data
+ * len: How many bytes to read/write
+ *
+ * Returns: 0 on success, not 0 on failure
+ */
+int i2c_read(uint8_t chip, unsigned int addr, int alen,
+ uint8_t *buffer, int len);
+
+int i2c_write(uint8_t chip, unsigned int addr, int alen,
+ uint8_t *buffer, int len);
+#endif
diff --git a/include/drivers/marvell/amb_adec.h b/include/drivers/marvell/amb_adec.h
new file mode 100644
index 00000000..ad782537
--- /dev/null
+++ b/include/drivers/marvell/amb_adec.h
@@ -0,0 +1,68 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _AMB_ADEC_H_
+#define _AMB_ADEC_H_
+
+#include <stdint.h>
+
+struct amb_win {
+ uint32_t base_addr;
+ uint32_t win_size;
+ uint32_t attribute;
+};
+
+enum amb_attribute_ids {
+ AMB_SPI0_CS0_ID = 0x1E,
+ AMB_SPI0_CS1_ID = 0x5E,
+ AMB_SPI0_CS2_ID = 0x9E,
+ AMB_SPI0_CS3_ID = 0xDE,
+ AMB_SPI1_CS0_ID = 0x1A,
+ AMB_SPI1_CS1_ID = 0x5A,
+ AMB_SPI1_CS2_ID = 0x9A,
+ AMB_SPI1_CS3_ID = 0xDA,
+ AMB_DEV_CS0_ID = 0x3E,
+ AMB_DEV_CS1_ID = 0x3D,
+ AMB_DEV_CS2_ID = 0x3B,
+ AMB_DEV_CS3_ID = 0x37,
+ AMB_BOOT_CS_ID = 0x2f,
+ AMB_BOOT_ROM_ID = 0x1D,
+};
+
+#define AMB_MAX_WIN_ID 7
+
+int init_amb_adec(int cp_index);
+
+#endif /* _AMB_ADEC_H_ */
+
diff --git a/include/drivers/marvell/cache_llc.h b/include/drivers/marvell/cache_llc.h
new file mode 100644
index 00000000..2c8d65db
--- /dev/null
+++ b/include/drivers/marvell/cache_llc.h
@@ -0,0 +1,33 @@
+/*
+ * ***************************************************************************
+ * Copyright (C) 2015 Marvell International Ltd.
+ * ***************************************************************************
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 2 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * ***************************************************************************
+ */
+
+#ifndef _CACHE_LLC_H_
+#define _CACHE_LLC_H_
+
+void llc_cache_sync(void);
+void llc_flush_all(void);
+void llc_clean_all(void);
+void llc_inv_all(void);
+void llc_disable(void);
+void llc_enable(int excl_mode);
+int llc_is_exclusive(void);
+void llc_save(void);
+void llc_resume(void);
+
+#endif /* _CACHE_LLC_H_ */
+
diff --git a/include/drivers/marvell/ccu.h b/include/drivers/marvell/ccu.h
new file mode 100644
index 00000000..748d72b1
--- /dev/null
+++ b/include/drivers/marvell/ccu.h
@@ -0,0 +1,63 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _CCU_H_
+#define _CCU_H_
+
+#include <stdint.h>
+
+struct ccu_win {
+ uint32_t base_addr_high;
+ uint32_t base_addr_low;
+ uint32_t win_size_high;
+ uint32_t win_size_low;
+ uint32_t target_id;
+};
+
+enum ccu_target_ids {
+ IO_0_TID = 0x00,
+ DRAM_0_TID = 0x03,
+ IO_1_TID = 0x0F,
+ CFG_REG_TID = 0x10,
+ RAR_TID = 0x20,
+ SRAM_TID = 0x40,
+ DRAM_1_TID = 0xC0,
+ CCU_MAX_TID,
+ INVALID_TID = 0xFF
+};
+
+int init_ccu(void);
+
+#endif /* _CCU_H_ */
+
diff --git a/include/drivers/marvell/i2c.h b/include/drivers/marvell/i2c.h
new file mode 100644
index 00000000..e26add9d
--- /dev/null
+++ b/include/drivers/marvell/i2c.h
@@ -0,0 +1,46 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _I2C_H_
+#define _I2C_H_
+
+
+void i2c_init(void);
+
+int i2c_read(uint8_t chip, unsigned int addr, int alen,
+ uint8_t *buffer, int len);
+
+int i2c_write(uint8_t chip, unsigned int addr, int alen,
+ uint8_t *buffer, int len);
+#endif
diff --git a/include/drivers/marvell/icu.h b/include/drivers/marvell/icu.h
new file mode 100644
index 00000000..5c14a81f
--- /dev/null
+++ b/include/drivers/marvell/icu.h
@@ -0,0 +1,60 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _ICU_H_
+#define _ICU_H_
+
+struct icu_irq {
+ uint8_t icu_id;
+ uint8_t spi_id;
+ uint8_t is_edge;
+};
+
+struct icu_config_entry {
+ const struct icu_irq *map;
+ int size;
+};
+
+struct icu_config {
+ struct icu_config_entry ns_multi;
+ struct icu_config_entry ns_single;
+ struct icu_config_entry sei;
+ struct icu_config_entry rei;
+};
+
+void icu_init(int cp_index, int spi_base, int spi_offset,
+ const struct icu_config *config);
+
+#endif /* _ICU_H_ */
+
diff --git a/include/drivers/marvell/iob.h b/include/drivers/marvell/iob.h
new file mode 100644
index 00000000..4fb328da
--- /dev/null
+++ b/include/drivers/marvell/iob.h
@@ -0,0 +1,61 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _IOB_H_
+#define _IOB_H_
+
+struct iob_win {
+ uint32_t base_addr_high;
+ uint32_t base_addr_low;
+ uint32_t win_size_high;
+ uint32_t win_size_low;
+ uint32_t target_id;
+};
+
+enum target_ids_iob {
+ INTERNAL_TID = 0x0,
+ MCI0_TID = 0x1,
+ PEX1_TID = 0x2,
+ PEX2_TID = 0x3,
+ PEX0_TID = 0x4,
+ NAND_TID = 0x5,
+ RUNIT_TID = 0x6,
+ MCI1_TID = 0x7,
+ IOB_MAX_TID
+};
+
+int init_iob(int cp_index);
+
+#endif /* _IOB_H_ */
+
diff --git a/include/drivers/marvell/mci.h b/include/drivers/marvell/mci.h
new file mode 100644
index 00000000..3a46f1e4
--- /dev/null
+++ b/include/drivers/marvell/mci.h
@@ -0,0 +1,260 @@
+/*
+ * ***************************************************************************
+ * Copyright (C) 2016 Marvell International Ltd.
+ * ***************************************************************************
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Marvell nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************************
+ */
+
+#ifndef _MCI_H_
+#define _MCI_H_
+
+/* MCI indirect access definitions */
+#define MCI_MAX_UNIT_ID 2
+/* SoC RFU / IHBx4 Control */
+#define MCIX4_REG_START_ADDRESS_REG(unit_id) (MVEBU_REGS_BASE + 0x6F4218 + (unit_id * 0x20))
+#define MCI_REMAP_OFF_SHIFT 8
+
+/* /HB /Units /Direct_regs /Direct regs /Configuration Register Write/Read Data Register */
+#define MCI_WRITE_READ_DATA_REG(mci_index) MVEBU_MCI_REG_BASE_REMAP(mci_index)
+/* /HB /Units /Direct_regs /Direct regs /Configuration Register Access Command Register */
+#define MCI_ACCESS_CMD_REG(mci_index) (MVEBU_MCI_REG_BASE_REMAP(mci_index) + 0x4)
+/* Access Command fields :
+ * bit[3:0] - Sub command: 1 => Periferal Config Register Read,
+ * 0 => Periferal Config Refister Write,
+ * 2 => Periferal Assign ID request,
+ * 3 => Circular Config Write
+ * bit[5] - 1 => Local (same chip access) 0 => Remote
+ * bit[15:8] - Destination hop ID. Put Global ID (GID) here (see scheme below).
+ * bit[23:22] - 0x3 IHB PHY REG address space, 0x0 IHB Controller space
+ * bit[21:16] - Low 6 bits of offset. Hight 2 bits are taken from bit[28:27]
+ * of IHB_PHY_CTRL (must be set before any PHY register access occures):
+ * /IHB_REG /IHB_REGInterchip Hopping Bus Registers /IHB Version Control Register
+ *
+ * ixi_ihb_top IHB PHY
+ * AXI ----------------------------- -------------
+ * <--| axi_hb_top | ihb_pipe_top |-->| |
+ * -->| GID=1 | GID=0 |<--| |
+ * ----------------------------- -------------
+ */
+#define MCI_INDIRECT_CTRL_READ_CMD 0x1
+#define MCI_INDIRECT_CTRL_ASSIGN_CMD 0x2
+#define MCI_INDIRECT_CTRL_CIRCULAR_CMD 0x3
+#define MCI_INDIRECT_CTRL_LOCAL_PKT (1 << 5)
+#define MCI_INDIRECT_CTRL_CMD_DONE_OFFSET 6
+#define MCI_INDIRECT_CTRL_CMD_DONE (1 << MCI_INDIRECT_CTRL_CMD_DONE_OFFSET)
+#define MCI_INDIRECT_CTRL_DATA_READY_OFFSET 7
+#define MCI_INDIRECT_CTRL_DATA_READY (1 << MCI_INDIRECT_CTRL_DATA_READY_OFFSET)
+#define MCI_INDIRECT_CTRL_HOPID_OFFSET 8
+#define MCI_INDIRECT_CTRL_HOPID(id) (((id) & 0xFF) << MCI_INDIRECT_CTRL_HOPID_OFFSET)
+#define MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET 16
+#define MCI_INDIRECT_REG_CTRL_ADDR(reg_num) (reg_num << MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET)
+/* PHY access domain */
+#define MCI_INDIRECT_CTRL_PHY_ACCESS_EN (0xC0 << MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET)
+/* Hop ID values */
+#define GID_IHB_PIPE 0
+#define GID_AXI_HB 1
+#define GID_IHB_EXT 2
+
+
+#define MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG 0x2
+/* Target MCi Local ID (LID, which is = self DID) */
+#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(val) (((val) & 0xFF) << 16)
+/* Bits [15:8]: Number of MCis on chip of target MCi */
+#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(val) (((val) & 0xFF) << 8)
+/* Bits [7:0]: Number of hops on chip of target MCi */
+#define MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(val) (((val) & 0xFF) << 0)
+
+/* IHB_REG domain registers */
+/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/
+ * Rx Memory Configuration Register (RX_MEM_CFG) */
+#define MCI_CTRL_RX_MEM_CFG_REG_NUM 0x0
+#define MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(val) (((val) & 0xFF) << 24)
+#define MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(val) (((val) & 0xFF) << 16)
+#define MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(val) (((val) & 0xFF) << 8)
+#define MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(val) (((val) & 0xF) << 4)
+#define MCI_CTRL_RX_TX_MEM_CFG_RTC(val) (((val) & 0x3) << 2)
+#define MCI_CTRL_RX_TX_MEM_CFG_WTC(val) (((val) & 0x3) << 0)
+#define MCI_CTRL_RX_MEM_CFG_REG_DEF_VAL (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x8) | \
+ MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x8) | \
+ MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x8) | \
+ MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(3) | \
+ MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \
+ MCI_CTRL_RX_TX_MEM_CFG_WTC(1))
+
+
+/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/
+ * Tx Memory Configuration Register (TX_MEM_CFG) */
+#define MCI_CTRL_TX_MEM_CFG_REG_NUM 0x1
+/* field mapping for TX mem config register are the as for RX register - see register above */
+#define MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x20) | \
+ MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x20) | \
+ MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x20) | \
+ MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(2) | \
+ MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \
+ MCI_CTRL_RX_TX_MEM_CFG_WTC(1))
+
+/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers /IHB Link CRC Control */
+/* MCi Link CRC Control Register (MCi_CRC_CTRL) */
+#define MCI_LINK_CRC_CTRL_REG_NUM 0x4
+
+/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers /IHB Status Register */
+/* MCi Status Register (MCi_STS) */
+#define MCI_CTRL_STATUS_REG_NUM 0x5
+#define MCI_CTRL_STATUS_REG_PHY_READY (1 << 12)
+#define MCI_CTRL_STATUS_REG_LINK_PRESENT (1 << 15)
+#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET 24
+#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK (0xF << MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET)
+/* Expected successful Link result, including reserved bit */
+#define MCI_CTRL_PHY_READY (MCI_CTRL_STATUS_REG_PHY_READY | \
+ MCI_CTRL_STATUS_REG_LINK_PRESENT | \
+ MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK)
+
+/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/
+ * MCi PHY Speed Settings Register (MCi_PHY_SETTING) */
+#define MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM 0x8
+#define MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(val) (((val) & 0xF) << 28)
+#define MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(val) (((val) & 0xF) << 12)
+#define MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(val) (((val) & 0xF) << 8)
+#define MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(val) (((val) & 0xF) << 4)
+#define MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(val) (((val) & 0x1) << 1)
+#define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \
+ MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \
+ MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x2) | \
+ MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1))
+
+/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers /IHB Mode Config */
+#define MCI_CTRL_IHB_MODE_CFG_REG_NUM 0x25
+#define MCI_CTRL_IHB_MODE_HBCLK_DIV(val) ((val) & 0xFF)
+#define MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET 8
+#define MCI_CTRL_IHB_MODE_CHUNK_MOD (1 << MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET)
+#define MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET 9
+#define MCI_CTRL_IHB_MODE_FWD_MOD (1 << MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET)
+#define MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(val) (((val) & 0xF) << 12)
+#define MCI_CTRL_IHB_MODE_RX_COMB_THRESH(val) (((val) & 0xFF) << 16)
+#define MCI_CTRL_IHB_MODE_TX_COMB_THRESH(val) (((val) & 0xFF) << 24)
+#define MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL (MCI_CTRL_IHB_MODE_HBCLK_DIV(7) | \
+ MCI_CTRL_IHB_MODE_FWD_MOD | \
+ MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(0xF) | \
+ MCI_CTRL_IHB_MODE_RX_COMB_THRESH(0x2D) | \
+ MCI_CTRL_IHB_MODE_TX_COMB_THRESH(0x45))
+
+#define MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL_A1 (MCI_CTRL_IHB_MODE_HBCLK_DIV(6) | \
+ MCI_CTRL_IHB_MODE_FWD_MOD | \
+ MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(0xF) | \
+ MCI_CTRL_IHB_MODE_RX_COMB_THRESH(0x0b) | \
+ MCI_CTRL_IHB_MODE_TX_COMB_THRESH(0x40))
+/* AXI_HB registers */
+#define MCI_AXI_ACCESS_DATA_REG_NUM 0x0
+#define MCI_AXI_ACCESS_PCIE_MODE 1
+#define MCI_AXI_ACCESS_CACHE_CHECK_OFFSET 5
+#define MCI_AXI_ACCESS_CACHE_CHECK (1 << MCI_AXI_ACCESS_CACHE_CHECK_OFFSET)
+#define MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET 6
+#define MCI_AXI_ACCESS_FORCE_POST_WR (1 << MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET)
+#define MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET 9
+#define MCI_AXI_ACCESS_DISABLE_CLK_GATING (1 << MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET)
+
+/* /HB /Units /HB_REG /HB_REGHopping Bus Registers /Window 0 Address Mask Register */
+#define MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM 0x2
+
+/* /HB /Units /HB_REG /HB_REGHopping Bus Registers /Window 0 Destination Register */
+#define MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM 0x3
+#define MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(val) (((val) & 0x1) << 16)
+#define MCI_HB_CTRL_WIN0_DEST_ID(val) (((val) & 0xfF) << 0)
+
+/* /HB /Units /HB_REG /HB_REGHopping Bus Registers /Tx Control Register */
+#define MCI_HB_CTRL_TX_CTRL_REG_NUM 0xD
+#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET 24
+#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE (1 << MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET)
+#define MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(val) (((val) & 0xF) << 12)
+#define MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(val) (((val) & 0xF) << 6)
+#define MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(val) (((val) & 0xF) << 0)
+
+/* HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers /IHB PHY Idle Control Register */
+#define MCI_PHY_P0_IDLE_CTRL_REG_NUM 0x6
+#define MCI_PHY_P0_IDLE_MIN_IDLE_COUNT_OFFSET 12
+#define MCI_PHY_P0_IDLE_MIN_IDLE_COUNT (0xF << MCI_PHY_P0_IDLE_MIN_IDLE_COUNT_OFFSET)
+#define MCI_PHY_P0_IDLE_SW_PWR_REQ_EN_OFFSET 16
+#define MCI_PHY_P0_IDLE_SW_PWR_REQ_EN (1 << MCI_PHY_P0_IDLE_SW_PWR_REQ_EN_OFFSET)
+#define MCI_PHY_P0_IDLE_SW_RETRAIN_MODE_OFFSET 20
+#define MCI_PHY_P0_IDLE_SW_RETRAIN_MODE (1 << MCI_PHY_P0_IDLE_SW_RETRAIN_MODE_OFFSET)
+
+/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers /IHB Version Control Register */
+#define MCI_PHY_CTRL_REG_NUM 0x7
+#define MCI_PHY_CTRL_MCI_MINOR 0x6 /* BITS [3:0] */
+#define MCI_PHY_CTRL_MCI_MINOR_A1 0x8 /* BITS [3:0] */
+#define MCI_PHY_CTRL_MCI_MAJOR_OFFSET 4
+#define MCI_PHY_CTRL_MCI_MAJOR (1 << MCI_PHY_CTRL_MCI_MAJOR_OFFSET)
+#define MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET 11
+#define MCI_PHY_CTRL_MCI_SLEEP_REQ (1 << MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET)
+#define MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET 24 /* Host=1 / Device=0 PHY mode */
+#define MCI_PHY_CTRL_MCI_PHY_MODE_HOST (1 << MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET)
+#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET 25 /* Register=1 / PWM=0 interface */
+#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE (1 << MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET)
+#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET 26 /* PHY code InReset=1 */
+#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE (1 << MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET)
+#define MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET 27
+#define MCI_PHY_CTRL_PHY_ADDR_MSB(addr) (((addr) & 0x3) << MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET)
+#define MCI_PHY_CTRL_PIDI_MODE_OFFSET 31
+#define MCI_PHY_CTRL_PIDI_MODE (1 << MCI_PHY_CTRL_PIDI_MODE_OFFSET)
+/* /IHB_8G_X4_PHY_V /Units /Registers /PWM Control Register 2 */
+#define MCI_PHY_PWM2_REG_NUM 0x6
+#define PWM2_SPEED_V3_8G (3)
+#define PWM2_SPEED_V2_4G (2)
+#define PWM2_SPEED_V1_2G (1)
+#define PWM2_SPEED_V0_1G (0)
+#define PWM2_SPEED_FORCE_OFFSET 10
+#define PWM2_SPEED_FORCE (1 << PWM2_SPEED_FORCE_OFFSET)
+#define PWM2_RX_LINE_EN_OFFSET 21
+#define PWM2_RX_LINE_EN (1 << PWM2_RX_LINE_EN_OFFSET)
+#define PWM2_TX_LINE_EN_OFFSET 29
+#define PWM2_TX_LINE_EN (1 << PWM2_TX_LINE_EN_OFFSET)
+
+/* /IHB_8G_X4_PHY_V /Units /Registers /PWM Control Register 3 */
+#define MCI_PHY_PWM3_REG_NUM 0x7
+#define PWM3_LINK_ERROR_OFFSET 8 /* [11:8] : LINK_ERROR */
+#define PWM3_LINK_ERROR_MASK (0xF << PWM3_LINK_ERROR_OFFSET)
+#define PWM3_NUM_OF_LANES_OFFSET 20 /* [20:22] : AUTO_NUMBER_OF_LANES */
+#define PWM3_NUM_OF_LANES_MASK (0x7 << PWM3_NUM_OF_LANES_OFFSET)
+#define PWM3_LINK_SPEED_MASK 0x7 /* [3:0] AUTO_SPEED */
+
+/* Number of times to wait for the MCI link ready after MCI configurations
+ * Normally takes 34-35 successive reads
+ */
+#define LINK_READY_TIMEOUT 100
+
+enum mci_register_type {
+ MCI_REG_TYPE_PHY = 0,
+ MCI_REG_TYPE_CTRL,
+};
+
+void mci_remap_indirect_access_base(void);
+int mci_initialize(int mci_index);
+
+#endif /* _MCI_H_ */
diff --git a/include/drivers/marvell/mochi/apn806_setup.h b/include/drivers/marvell/mochi/apn806_setup.h
new file mode 100644
index 00000000..ca41269e
--- /dev/null
+++ b/include/drivers/marvell/mochi/apn806_setup.h
@@ -0,0 +1,60 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+#ifndef __APN806_SETUP_H__
+#define __APN806_SETUP_H__
+
+#include <mmio.h>
+
+#define APN806_REV_ID_A0 0
+#define APN806_REV_ID_A1 1
+
+/* APN806 revision ID */
+#define MVEBU_CSS_GWD_CTRL_IIDR2_REG (MVEBU_REGS_BASE + 0x610FCC)
+#define GWD_IIDR2_REV_ID_OFFSET 12
+#define GWD_IIDR2_REV_ID_MASK 0xF
+
+void apn806_init(void);
+
+static inline int apn806_rev_id_get(void)
+{
+ /* Returns:
+ * - 0 (APN806_REV_ID_A0) for A0
+ * - 1 (APN806_REV_ID_A1) for A1
+ */
+ return (mmio_read_32(MVEBU_CSS_GWD_CTRL_IIDR2_REG) >>
+ GWD_IIDR2_REV_ID_OFFSET) &
+ GWD_IIDR2_REV_ID_MASK;
+}
+
+#endif /* __APN806_SETUP_H__ */
diff --git a/include/drivers/marvell/mochi/cp110_setup.h b/include/drivers/marvell/mochi/cp110_setup.h
new file mode 100644
index 00000000..6ccbaaa5
--- /dev/null
+++ b/include/drivers/marvell/mochi/cp110_setup.h
@@ -0,0 +1,59 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+#ifndef __PLAT_CP110_H__
+#define __PLAT_CP110_H__
+
+#define MVEBU_DEVICE_ID_REG (MVEBU_CP_DFX_BASE(0) + 0x40)
+#define MVEBU_DEVICE_ID_OFFSET (0)
+#define MVEBU_DEVICE_ID_MASK (0xffff << MVEBU_DEVICE_ID_OFFSET)
+#define MVEBU_DEVICE_REV_OFFSET (16)
+#define MVEBU_DEVICE_REV_MASK (0xf << MVEBU_DEVICE_REV_OFFSET)
+#define MVEBU_70X0_DEV_ID (0x7040)
+#define MVEBU_80X0_DEV_ID (0x8040)
+
+static inline uint32_t cp110_device_id_get(void)
+{
+ /* Returns:
+ * - MVEBU_70X0_DEV_ID for A70X0 family
+ * - MVEBU_80X0_DEV_ID for A80X0 family
+ */
+ return (mmio_read_32(MVEBU_DEVICE_ID_REG) >>
+ MVEBU_DEVICE_ID_OFFSET) &
+ MVEBU_DEVICE_ID_MASK;
+}
+
+void cp110_init(int cp_index);
+void cp110_ble_init(int cp_index);
+
+#endif /* __PLAT_CP110_H__ */
diff --git a/include/drivers/marvell/rfu.h b/include/drivers/marvell/rfu.h
new file mode 100644
index 00000000..1b09bb87
--- /dev/null
+++ b/include/drivers/marvell/rfu.h
@@ -0,0 +1,64 @@
+/*
+* ***************************************************************************
+* Copyright (C) 2016 Marvell International Ltd.
+* ***************************************************************************
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* Neither the name of Marvell nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific
+* prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+***************************************************************************
+*/
+
+#ifndef _RFU_H_
+#define _RFU_H_
+
+#include <stdint.h>
+
+struct rfu_win {
+ uint32_t base_addr_high;
+ uint32_t base_addr_low;
+ uint32_t win_size_high;
+ uint32_t win_size_low;
+ uint32_t target_id;
+};
+
+enum rfu_target_ids {
+ MCI_0_TID = 0x0,
+ MCI_1_TID = 0x1,
+ MCI_2_TID = 0x2,
+ PIDI_TID = 0x3,
+ SPI_TID = 0x4,
+ STM_TID = 0x5,
+ BOOTROM_TID = 0x6,
+ RFU_MAX_TID
+};
+
+#define RFU_MAX_WIN_ID 7
+
+int init_rfu(void);
+
+#endif /* _RFU_H_ */
+