aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/phy/marvell
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/phy/marvell')
-rw-r--r--roms/u-boot/drivers/phy/marvell/Kconfig9
-rw-r--r--roms/u-boot/drivers/phy/marvell/Makefile6
-rw-r--r--roms/u-boot/drivers/phy/marvell/comphy_a3700.c1019
-rw-r--r--roms/u-boot/drivers/phy/marvell/comphy_a3700.h263
-rw-r--r--roms/u-boot/drivers/phy/marvell/comphy_core.c215
-rw-r--r--roms/u-boot/drivers/phy/marvell/comphy_core.h144
-rw-r--r--roms/u-boot/drivers/phy/marvell/comphy_cp110.c681
-rw-r--r--roms/u-boot/drivers/phy/marvell/comphy_mux.c135
-rw-r--r--roms/u-boot/drivers/phy/marvell/sata.h29
-rw-r--r--roms/u-boot/drivers/phy/marvell/utmi_phy.h101
10 files changed, 2602 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/phy/marvell/Kconfig b/roms/u-boot/drivers/phy/marvell/Kconfig
new file mode 100644
index 000000000..424002840
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/Kconfig
@@ -0,0 +1,9 @@
+config MVEBU_COMPHY_SUPPORT
+ bool "ComPhy SerDes driver"
+ default n
+ help
+ Choose this option to add support
+ for Comphy driver.
+ This driver passes over the lanes
+ and initialize the lane depends on the
+ type and speed.
diff --git a/roms/u-boot/drivers/phy/marvell/Makefile b/roms/u-boot/drivers/phy/marvell/Makefile
new file mode 100644
index 000000000..51be0399e
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_core.o
+obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_mux.o
+obj-$(CONFIG_ARMADA_3700) += comphy_a3700.o
+obj-$(CONFIG_ARMADA_8K) += comphy_cp110.o
diff --git a/roms/u-boot/drivers/phy/marvell/comphy_a3700.c b/roms/u-boot/drivers/phy/marvell/comphy_a3700.c
new file mode 100644
index 000000000..06822d1d1
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/comphy_a3700.c
@@ -0,0 +1,1019 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <linux/delay.h>
+
+#include "comphy_a3700.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct comphy_mux_data a3700_comphy_mux_data[] = {
+ /* Lane 0 */
+ {
+ 4,
+ {
+ { COMPHY_TYPE_UNCONNECTED, 0x0 },
+ { COMPHY_TYPE_SGMII1, 0x0 },
+ { COMPHY_TYPE_USB3_HOST0, 0x1 },
+ { COMPHY_TYPE_USB3_DEVICE, 0x1 }
+ }
+ },
+ /* Lane 1 */
+ {
+ 3,
+ {
+ { COMPHY_TYPE_UNCONNECTED, 0x0},
+ { COMPHY_TYPE_SGMII0, 0x0},
+ { COMPHY_TYPE_PEX0, 0x1}
+ }
+ },
+ /* Lane 2 */
+ {
+ 4,
+ {
+ { COMPHY_TYPE_UNCONNECTED, 0x0},
+ { COMPHY_TYPE_SATA0, 0x0},
+ { COMPHY_TYPE_USB3_HOST0, 0x1},
+ { COMPHY_TYPE_USB3_DEVICE, 0x1}
+ }
+ },
+};
+
+struct sgmii_phy_init_data_fix {
+ u16 addr;
+ u16 value;
+};
+
+/* Changes to 40M1G25 mode data required for running 40M3G125 init mode */
+static struct sgmii_phy_init_data_fix sgmii_phy_init_fix[] = {
+ {0x005, 0x07CC}, {0x015, 0x0000}, {0x01B, 0x0000}, {0x01D, 0x0000},
+ {0x01E, 0x0000}, {0x01F, 0x0000}, {0x020, 0x0000}, {0x021, 0x0030},
+ {0x026, 0x0888}, {0x04D, 0x0152}, {0x04F, 0xA020}, {0x050, 0x07CC},
+ {0x053, 0xE9CA}, {0x055, 0xBD97}, {0x071, 0x3015}, {0x076, 0x03AA},
+ {0x07C, 0x0FDF}, {0x0C2, 0x3030}, {0x0C3, 0x8000}, {0x0E2, 0x5550},
+ {0x0E3, 0x12A4}, {0x0E4, 0x7D00}, {0x0E6, 0x0C83}, {0x101, 0xFCC0},
+ {0x104, 0x0C10}
+};
+
+/* 40M1G25 mode init data */
+static u16 sgmii_phy_init[512] = {
+ /* 0 1 2 3 4 5 6 7 */
+ /*-----------------------------------------------------------*/
+ /* 8 9 A B C D E F */
+ 0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26, /* 00 */
+ 0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52, /* 08 */
+ 0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000, /* 10 */
+ 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF, /* 18 */
+ 0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000, /* 20 */
+ 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 28 */
+ 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */
+ 0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100, /* 38 */
+ 0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00, /* 40 */
+ 0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A, /* 48 */
+ 0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001, /* 50 */
+ 0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF, /* 58 */
+ 0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000, /* 60 */
+ 0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002, /* 68 */
+ 0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780, /* 70 */
+ 0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000, /* 78 */
+ 0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000, /* 80 */
+ 0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210, /* 88 */
+ 0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F, /* 90 */
+ 0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651, /* 98 */
+ 0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000, /* A0 */
+ 0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* A8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* B0 */
+ 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000, /* B8 */
+ 0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003, /* C0 */
+ 0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000, /* C8 */
+ 0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00, /* D0 */
+ 0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000, /* D8 */
+ 0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541, /* E0 */
+ 0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200, /* E8 */
+ 0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000, /* F0 */
+ 0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000, /* F8 */
+ 0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000, /*100 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*108 */
+ 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000, /*110 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*118 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*120 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*128 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*130 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*138 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*140 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*148 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*150 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*158 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*160 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*168 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*170 */
+ 0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000, /*178 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*180 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*188 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*190 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*198 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1F0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /*1F8 */
+};
+
+/*
+ * comphy_poll_reg
+ *
+ * return: 1 on success, 0 on timeout
+ */
+static u32 comphy_poll_reg(void *addr, u32 val, u32 mask, u8 op_type)
+{
+ u32 rval = 0xDEAD, timeout;
+
+ for (timeout = PLL_LOCK_TIMEOUT; timeout > 0; timeout--) {
+ if (op_type == POLL_16B_REG)
+ rval = readw(addr); /* 16 bit */
+ else
+ rval = readl(addr) ; /* 32 bit */
+
+ if ((rval & mask) == val)
+ return 1;
+
+ udelay(10000);
+ }
+
+ debug("Time out waiting (%p = %#010x)\n", addr, rval);
+ return 0;
+}
+
+/*
+ * comphy_pcie_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_pcie_power_up(u32 speed, u32 invert)
+{
+ int ret;
+
+ debug_enter();
+
+ /*
+ * 1. Enable max PLL.
+ */
+ reg_set16(phy_addr(PCIE, LANE_CFG1), bf_use_max_pll_rate, 0);
+
+ /*
+ * 2. Select 20 bit SERDES interface.
+ */
+ reg_set16(phy_addr(PCIE, GLOB_CLK_SRC_LO), bf_cfg_sel_20b, 0);
+
+ /*
+ * 3. Force to use reg setting for PCIe mode
+ */
+ reg_set16(phy_addr(PCIE, MISC_REG1), bf_sel_bits_pcie_force, 0);
+
+ /*
+ * 4. Change RX wait
+ */
+ reg_set16(phy_addr(PCIE, PWR_MGM_TIM1), 0x10C, 0xFFFF);
+
+ /*
+ * 5. Enable idle sync
+ */
+ reg_set16(phy_addr(PCIE, UNIT_CTRL), 0x60 | rb_idle_sync_en, 0xFFFF);
+
+ /*
+ * 6. Enable the output of 100M/125M/500M clock
+ */
+ reg_set16(phy_addr(PCIE, MISC_REG0),
+ 0xA00D | rb_clk500m_en | rb_clk100m_125m_en, 0xFFFF);
+
+ /*
+ * 7. Enable TX
+ */
+ reg_set(PCIE_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF);
+
+ /*
+ * 8. Check crystal jumper setting and program the Power and PLL
+ * Control accordingly
+ */
+ if (get_ref_clk() == 40) {
+ /* 40 MHz */
+ reg_set16(phy_addr(PCIE, PWR_PLL_CTRL), 0xFC63, 0xFFFF);
+ } else {
+ /* 25 MHz */
+ reg_set16(phy_addr(PCIE, PWR_PLL_CTRL), 0xFC62, 0xFFFF);
+ }
+
+ /*
+ * 9. Override Speed_PLL value and use MAC PLL
+ */
+ reg_set16(phy_addr(PCIE, KVCO_CAL_CTRL), 0x0040 | rb_use_max_pll_rate,
+ 0xFFFF);
+
+ /*
+ * 10. Check the Polarity invert bit
+ */
+ if (invert & COMPHY_POLARITY_TXD_INVERT)
+ reg_set16(phy_addr(PCIE, SYNC_PATTERN), phy_txd_inv, 0);
+
+ if (invert & COMPHY_POLARITY_RXD_INVERT)
+ reg_set16(phy_addr(PCIE, SYNC_PATTERN), phy_rxd_inv, 0);
+
+ /*
+ * 11. Release SW reset
+ */
+ reg_set16(phy_addr(PCIE, GLOB_PHY_CTRL0),
+ rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32,
+ bf_soft_rst | bf_mode_refdiv);
+
+ /* Wait for > 55 us to allow PCLK be enabled */
+ udelay(PLL_SET_DELAY_US);
+
+ /* Assert PCLK enabled */
+ ret = comphy_poll_reg(phy_addr(PCIE, LANE_STAT1), /* address */
+ rb_txdclk_pclk_en, /* value */
+ rb_txdclk_pclk_en, /* mask */
+ POLL_16B_REG); /* 16bit */
+ if (!ret)
+ printf("Failed to lock PCIe PLL\n");
+
+ debug_exit();
+
+ /* Return the status of the PLL */
+ return ret;
+}
+
+/*
+ * reg_set_indirect
+ *
+ * return: void
+ */
+static void reg_set_indirect(u32 reg, u16 data, u16 mask)
+{
+ reg_set(rh_vsreg_addr, reg, 0xFFFFFFFF);
+ reg_set(rh_vsreg_data, data, mask);
+}
+
+/*
+ * comphy_sata_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_sata_power_up(u32 invert)
+{
+ int ret;
+ u32 data = 0;
+
+ debug_enter();
+
+ /*
+ * 0. Check the Polarity invert bits
+ */
+ if (invert & COMPHY_POLARITY_TXD_INVERT)
+ data |= bs_txd_inv;
+
+ if (invert & COMPHY_POLARITY_RXD_INVERT)
+ data |= bs_rxd_inv;
+
+ reg_set_indirect(vphy_sync_pattern_reg, data, bs_txd_inv | bs_rxd_inv);
+
+ /*
+ * 1. Select 40-bit data width width
+ */
+ reg_set_indirect(vphy_loopback_reg0, 0x800, bs_phyintf_40bit);
+
+ /*
+ * 2. Select reference clock and PHY mode (SATA)
+ */
+ if (get_ref_clk() == 40) {
+ /* 40 MHz */
+ reg_set_indirect(vphy_power_reg0, 0x3, 0x00FF);
+ } else {
+ /* 20 MHz */
+ reg_set_indirect(vphy_power_reg0, 0x1, 0x00FF);
+ }
+
+ /*
+ * 3. Use maximum PLL rate (no power save)
+ */
+ reg_set_indirect(vphy_calctl_reg, bs_max_pll_rate, bs_max_pll_rate);
+
+ /*
+ * 4. Reset reserved bit (??)
+ */
+ reg_set_indirect(vphy_reserve_reg, 0, bs_phyctrl_frm_pin);
+
+ /*
+ * 5. Set vendor-specific configuration (??)
+ */
+ reg_set(rh_vs0_a, vsata_ctrl_reg, 0xFFFFFFFF);
+ reg_set(rh_vs0_d, bs_phy_pu_pll, bs_phy_pu_pll);
+
+ /* Wait for > 55 us to allow PLL be enabled */
+ udelay(PLL_SET_DELAY_US);
+
+ /* Assert SATA PLL enabled */
+ reg_set(rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF);
+ ret = comphy_poll_reg(rh_vsreg_data, /* address */
+ bs_pll_ready_tx, /* value */
+ bs_pll_ready_tx, /* mask */
+ POLL_32B_REG); /* 32bit */
+ if (!ret)
+ printf("Failed to lock SATA PLL\n");
+
+ debug_exit();
+
+ return ret;
+}
+
+/*
+ * usb3_reg_set16
+ *
+ * return: void
+ */
+static void usb3_reg_set16(u32 reg, u16 data, u16 mask, u32 lane)
+{
+ /*
+ * When Lane 2 PHY is for USB3, access the PHY registers
+ * through indirect Address and Data registers INDIR_ACC_PHY_ADDR
+ * (RD00E0178h [31:0]) and INDIR_ACC_PHY_DATA (RD00E017Ch [31:0])
+ * within the SATA Host Controller registers, Lane 2 base register
+ * offset is 0x200
+ */
+
+ if (lane == 2)
+ reg_set_indirect(USB3PHY_LANE2_REG_BASE_OFFSET + reg, data,
+ mask);
+ else
+ reg_set16(phy_addr(USB3, reg), data, mask);
+}
+
+/*
+ * comphy_usb3_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_usb3_power_up(u32 lane, u32 type, u32 speed, u32 invert)
+{
+ int ret;
+
+ debug_enter();
+
+ /*
+ * 1. Power up OTG module
+ */
+ reg_set(USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0);
+
+ /*
+ * 2. Set counter for 100us pulse in USB3 Host and Device
+ * restore default burst size limit (Reference Clock 31:24)
+ */
+ reg_set(USB3_CTRPUL_VAL_REG, 0x8 << 24, rb_usb3_ctr_100ns);
+
+
+ /* 0xd005c300 = 0x1001 */
+ /* set PRD_TXDEEMPH (3.5db de-emph) */
+ usb3_reg_set16(LANE_CFG0, 0x1, 0xFF, lane);
+
+ /*
+ * Set BIT0: enable transmitter in high impedance mode
+ * Set BIT[3:4]: delay 2 clock cycles for HiZ off latency
+ * Set BIT6: Tx detect Rx at HiZ mode
+ * Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db
+ * together with bit 0 of COMPHY_REG_LANE_CFG0_ADDR
+ * register
+ */
+ usb3_reg_set16(LANE_CFG1,
+ tx_det_rx_mode | gen2_tx_data_dly_deft
+ | tx_elec_idle_mode_en,
+ prd_txdeemph1_mask | tx_det_rx_mode
+ | gen2_tx_data_dly_mask | tx_elec_idle_mode_en, lane);
+
+ /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */
+ usb3_reg_set16(LANE_CFG4, bf_spread_spectrum_clock_en, 0x80, lane);
+
+ /*
+ * set Override Margining Controls From the MAC: Use margining signals
+ * from lane configuration
+ */
+ usb3_reg_set16(TEST_MODE_CTRL, rb_mode_margin_override, 0xFFFF, lane);
+
+ /* set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles */
+ /* set Mode Clock Source = PCLK is generated from REFCLK */
+ usb3_reg_set16(GLOB_CLK_SRC_LO, 0x0, 0xFF, lane);
+
+ /* set G2 Spread Spectrum Clock Amplitude at 4K */
+ usb3_reg_set16(GEN2_SETTINGS_2, g2_tx_ssc_amp, 0xF000, lane);
+
+ /*
+ * unset G3 Spread Spectrum Clock Amplitude & set G3 TX and RX Register
+ * Master Current Select
+ */
+ usb3_reg_set16(GEN2_SETTINGS_3, 0x0, 0xFFFF, lane);
+
+ /*
+ * 3. Check crystal jumper setting and program the Power and PLL
+ * Control accordingly
+ * 4. Change RX wait
+ */
+ if (get_ref_clk() == 40) {
+ /* 40 MHz */
+ usb3_reg_set16(PWR_PLL_CTRL, 0xFCA3, 0xFFFF, lane);
+ usb3_reg_set16(PWR_MGM_TIM1, 0x10C, 0xFFFF, lane);
+ } else {
+ /* 25 MHz */
+ usb3_reg_set16(PWR_PLL_CTRL, 0xFCA2, 0xFFFF, lane);
+ usb3_reg_set16(PWR_MGM_TIM1, 0x107, 0xFFFF, lane);
+ }
+
+ /*
+ * 5. Enable idle sync
+ */
+ usb3_reg_set16(UNIT_CTRL, 0x60 | rb_idle_sync_en, 0xFFFF, lane);
+
+ /*
+ * 6. Enable the output of 500M clock
+ */
+ usb3_reg_set16(MISC_REG0, 0xA00D | rb_clk500m_en, 0xFFFF, lane);
+
+ /*
+ * 7. Set 20-bit data width
+ */
+ usb3_reg_set16(DIG_LB_EN, 0x0400, 0xFFFF, lane);
+
+ /*
+ * 8. Override Speed_PLL value and use MAC PLL
+ */
+ usb3_reg_set16(KVCO_CAL_CTRL, 0x0040 | rb_use_max_pll_rate, 0xFFFF,
+ lane);
+
+ /*
+ * 9. Check the Polarity invert bit
+ */
+ if (invert & COMPHY_POLARITY_TXD_INVERT)
+ usb3_reg_set16(SYNC_PATTERN, phy_txd_inv, 0, lane);
+
+ if (invert & COMPHY_POLARITY_RXD_INVERT)
+ usb3_reg_set16(SYNC_PATTERN, phy_rxd_inv, 0, lane);
+
+ /*
+ * 10. Set max speed generation to USB3.0 5Gbps
+ */
+ usb3_reg_set16(SYNC_MASK_GEN, 0x0400, 0x0C00, lane);
+
+ /*
+ * 11. Set capacitor value for FFE gain peaking to 0xF
+ */
+ usb3_reg_set16(GEN3_SETTINGS_3, 0xF, 0xF, lane);
+
+ /*
+ * 12. Release SW reset
+ */
+ usb3_reg_set16(GLOB_PHY_CTRL0,
+ rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32
+ | 0x20, 0xFFFF, lane);
+
+ /* Wait for > 55 us to allow PCLK be enabled */
+ udelay(PLL_SET_DELAY_US);
+
+ /* Assert PCLK enabled */
+ if (lane == 2) {
+ reg_set(rh_vsreg_addr,
+ LANE_STAT1 + USB3PHY_LANE2_REG_BASE_OFFSET,
+ 0xFFFFFFFF);
+ ret = comphy_poll_reg(rh_vsreg_data, /* address */
+ rb_txdclk_pclk_en, /* value */
+ rb_txdclk_pclk_en, /* mask */
+ POLL_32B_REG); /* 32bit */
+ } else {
+ ret = comphy_poll_reg(phy_addr(USB3, LANE_STAT1), /* address */
+ rb_txdclk_pclk_en, /* value */
+ rb_txdclk_pclk_en, /* mask */
+ POLL_16B_REG); /* 16bit */
+ }
+ if (!ret)
+ printf("Failed to lock USB3 PLL\n");
+
+ /*
+ * Set Soft ID for Host mode (Device mode works with Hard ID
+ * detection)
+ */
+ if (type == COMPHY_TYPE_USB3_HOST0) {
+ /*
+ * set BIT0: set ID_MODE of Host/Device = "Soft ID" (BIT1)
+ * clear BIT1: set SOFT_ID = Host
+ * set BIT4: set INT_MODE = ID. Interrupt Mode: enable
+ * interrupt by ID instead of using both interrupts
+ * of HOST and Device ORed simultaneously
+ * INT_MODE=ID in order to avoid unexpected
+ * behaviour or both interrupts together
+ */
+ reg_set(USB32_CTRL_BASE,
+ usb32_ctrl_id_mode | usb32_ctrl_int_mode,
+ usb32_ctrl_id_mode | usb32_ctrl_soft_id |
+ usb32_ctrl_int_mode);
+ }
+
+ debug_exit();
+
+ return ret;
+}
+
+/*
+ * comphy_usb2_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_usb2_power_up(u8 usb32)
+{
+ int ret;
+
+ debug_enter();
+
+ if (usb32 != 0 && usb32 != 1) {
+ printf("invalid usb32 value: (%d), should be either 0 or 1\n",
+ usb32);
+ debug_exit();
+ return 0;
+ }
+
+ /*
+ * 0. Setup PLL. 40MHz clock uses defaults.
+ * See "PLL Settings for Typical REFCLK" table
+ */
+ if (get_ref_clk() == 25) {
+ reg_set(USB2_PHY_BASE(usb32), 5 | (96 << 16),
+ 0x3F | (0xFF << 16) | (0x3 << 28));
+ }
+
+ /*
+ * 1. PHY pull up and disable USB2 suspend
+ */
+ reg_set(USB2_PHY_CTRL_ADDR(usb32),
+ RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU(usb32), 0);
+
+ if (usb32 != 0) {
+ /*
+ * 2. Power up OTG module
+ */
+ reg_set(USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0);
+
+ /*
+ * 3. Configure PHY charger detection
+ */
+ reg_set(USB2_PHY_CHRGR_DET_ADDR, 0,
+ rb_cdp_en | rb_dcp_en | rb_pd_en | rb_cdp_dm_auto |
+ rb_enswitch_dp | rb_enswitch_dm | rb_pu_chrg_dtc);
+ }
+
+ /* Assert PLL calibration done */
+ ret = comphy_poll_reg(USB2_PHY_CAL_CTRL_ADDR(usb32),
+ rb_usb2phy_pllcal_done, /* value */
+ rb_usb2phy_pllcal_done, /* mask */
+ POLL_32B_REG); /* 32bit */
+ if (!ret)
+ printf("Failed to end USB2 PLL calibration\n");
+
+ /* Assert impedance calibration done */
+ ret = comphy_poll_reg(USB2_PHY_CAL_CTRL_ADDR(usb32),
+ rb_usb2phy_impcal_done, /* value */
+ rb_usb2phy_impcal_done, /* mask */
+ POLL_32B_REG); /* 32bit */
+ if (!ret)
+ printf("Failed to end USB2 impedance calibration\n");
+
+ /* Assert squetch calibration done */
+ ret = comphy_poll_reg(USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32),
+ rb_usb2phy_sqcal_done, /* value */
+ rb_usb2phy_sqcal_done, /* mask */
+ POLL_32B_REG); /* 32bit */
+ if (!ret)
+ printf("Failed to end USB2 unknown calibration\n");
+
+ /* Assert PLL is ready */
+ ret = comphy_poll_reg(USB2_PHY_PLL_CTRL0_ADDR(usb32),
+ rb_usb2phy_pll_ready, /* value */
+ rb_usb2phy_pll_ready, /* mask */
+ POLL_32B_REG); /* 32bit */
+
+ if (!ret)
+ printf("Failed to lock USB2 PLL\n");
+
+ debug_exit();
+
+ return ret;
+}
+
+/*
+ * comphy_emmc_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_emmc_power_up(void)
+{
+ debug_enter();
+
+ /*
+ * 1. Bus power ON, Bus voltage 1.8V
+ */
+ reg_set(SDIO_HOST_CTRL1_ADDR, 0xB00, 0xF00);
+
+ /*
+ * 2. Set FIFO parameters
+ */
+ reg_set(SDIO_SDHC_FIFO_ADDR, 0x315, 0xFFFFFFFF);
+
+ /*
+ * 3. Set Capabilities 1_2
+ */
+ reg_set(SDIO_CAP_12_ADDR, 0x25FAC8B2, 0xFFFFFFFF);
+
+ /*
+ * 4. Set Endian
+ */
+ reg_set(SDIO_ENDIAN_ADDR, 0x00c00000, 0);
+
+ /*
+ * 4. Init PHY
+ */
+ reg_set(SDIO_PHY_TIMING_ADDR, 0x80000000, 0x80000000);
+ reg_set(SDIO_PHY_PAD_CTRL0_ADDR, 0x50000000, 0xF0000000);
+
+ /*
+ * 5. DLL reset
+ */
+ reg_set(SDIO_DLL_RST_ADDR, 0xFFFEFFFF, 0);
+ reg_set(SDIO_DLL_RST_ADDR, 0x00010000, 0);
+
+ debug_exit();
+
+ return 1;
+}
+
+/*
+ * comphy_sgmii_power_up
+ *
+ * return:
+ */
+static void comphy_sgmii_phy_init(u32 lane, u32 speed)
+{
+ const int fix_arr_sz = ARRAY_SIZE(sgmii_phy_init_fix);
+ int addr, fix_idx;
+ u16 val;
+
+ fix_idx = 0;
+ for (addr = 0; addr < 512; addr++) {
+ /*
+ * All PHY register values are defined in full for 3.125Gbps
+ * SERDES speed. The values required for 1.25 Gbps are almost
+ * the same and only few registers should be "fixed" in
+ * comparison to 3.125 Gbps values. These register values are
+ * stored in "sgmii_phy_init_fix" array.
+ */
+ if (speed != COMPHY_SPEED_1_25G &&
+ sgmii_phy_init_fix[fix_idx].addr == addr) {
+ /* Use new value */
+ val = sgmii_phy_init_fix[fix_idx].value;
+ if (fix_idx < fix_arr_sz)
+ fix_idx++;
+ } else {
+ val = sgmii_phy_init[addr];
+ }
+
+ reg_set16(sgmiiphy_addr(lane, addr), val, 0xFFFF);
+ }
+}
+
+/*
+ * comphy_sgmii_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert)
+{
+ int ret;
+ u32 saved_selector;
+
+ debug_enter();
+
+ /*
+ * 1. Configure PHY to SATA/SAS mode by setting pin PIN_PIPE_SEL=0
+ */
+ saved_selector = readl(COMPHY_SEL_ADDR);
+ reg_set(COMPHY_SEL_ADDR, 0, 0xFFFFFFFF);
+
+ /*
+ * 2. Reset PHY by setting PHY input port PIN_RESET=1.
+ * 3. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep
+ * PHY TXP/TXN output to idle state during PHY initialization
+ * 4. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0.
+ */
+ reg_set(COMPHY_PHY_CFG1_ADDR(lane),
+ rb_pin_reset_comphy | rb_pin_tx_idle | rb_pin_pu_iveref,
+ rb_pin_reset_core | rb_pin_pu_pll |
+ rb_pin_pu_rx | rb_pin_pu_tx);
+
+ /*
+ * 5. Release reset to the PHY by setting PIN_RESET=0.
+ */
+ reg_set(COMPHY_PHY_CFG1_ADDR(lane), 0, rb_pin_reset_comphy);
+
+ /*
+ * 7. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide
+ * COMPHY bit rate
+ */
+ if (speed == COMPHY_SPEED_3_125G) { /* 3.125 GHz */
+ reg_set(COMPHY_PHY_CFG1_ADDR(lane),
+ (0x8 << rf_gen_rx_sel_shift) |
+ (0x8 << rf_gen_tx_sel_shift),
+ rf_gen_rx_select | rf_gen_tx_select);
+
+ } else if (speed == COMPHY_SPEED_1_25G) { /* 1.25 GHz */
+ reg_set(COMPHY_PHY_CFG1_ADDR(lane),
+ (0x6 << rf_gen_rx_sel_shift) |
+ (0x6 << rf_gen_tx_sel_shift),
+ rf_gen_rx_select | rf_gen_tx_select);
+ } else {
+ printf("Unsupported COMPHY speed!\n");
+ return 0;
+ }
+
+ /*
+ * 8. Wait 1mS for bandgap and reference clocks to stabilize;
+ * then start SW programming.
+ */
+ mdelay(10);
+
+ /* 9. Program COMPHY register PHY_MODE */
+ reg_set16(sgmiiphy_addr(lane, PWR_PLL_CTRL),
+ PHY_MODE_SGMII << rf_phy_mode_shift, rf_phy_mode_mask);
+
+ /*
+ * 10. Set COMPHY register REFCLK_SEL to select the correct REFCLK
+ * source
+ */
+ reg_set16(sgmiiphy_addr(lane, MISC_REG0), 0, rb_ref_clk_sel);
+
+ /*
+ * 11. Set correct reference clock frequency in COMPHY register
+ * REF_FREF_SEL.
+ */
+ if (get_ref_clk() == 40) {
+ reg_set16(sgmiiphy_addr(lane, PWR_PLL_CTRL),
+ 0x4 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask);
+ } else {
+ /* 25MHz */
+ reg_set16(sgmiiphy_addr(lane, PWR_PLL_CTRL),
+ 0x1 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask);
+ }
+
+ /* 12. Program COMPHY register PHY_GEN_MAX[1:0] */
+ /*
+ * This step is mentioned in the flow received from verification team.
+ * However the PHY_GEN_MAX value is only meaningful for other
+ * interfaces (not SGMII). For instance, it selects SATA speed
+ * 1.5/3/6 Gbps or PCIe speed 2.5/5 Gbps
+ */
+
+ /*
+ * 13. Program COMPHY register SEL_BITS to set correct parallel data
+ * bus width
+ */
+ /* 10bit */
+ reg_set16(sgmiiphy_addr(lane, DIG_LB_EN), 0, rf_data_width_mask);
+
+ /*
+ * 14. As long as DFE function needs to be enabled in any mode,
+ * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F
+ * for real chip during COMPHY power on.
+ */
+ /*
+ * The step 14 exists (and empty) in the original initialization flow
+ * obtained from the verification team. According to the functional
+ * specification DFE_UPDATE_EN already has the default value 0x3F
+ */
+
+ /*
+ * 15. Program COMPHY GEN registers.
+ * These registers should be programmed based on the lab testing
+ * result to achieve optimal performance. Please contact the CEA
+ * group to get the related GEN table during real chip bring-up.
+ * We only requred to run though the entire registers programming
+ * flow defined by "comphy_sgmii_phy_init" when the REF clock is
+ * 40 MHz. For REF clock 25 MHz the default values stored in PHY
+ * registers are OK.
+ */
+ debug("Running C-DPI phy init %s mode\n",
+ speed == COMPHY_SPEED_3_125G ? "2G5" : "1G");
+ if (get_ref_clk() == 40)
+ comphy_sgmii_phy_init(lane, speed);
+
+ /*
+ * 16. [Simulation Only] should not be used for real chip.
+ * By pass power up calibration by programming EXT_FORCE_CAL_DONE
+ * (R02h[9]) to 1 to shorten COMPHY simulation time.
+ */
+ /*
+ * 17. [Simulation Only: should not be used for real chip]
+ * Program COMPHY register FAST_DFE_TIMER_EN=1 to shorten RX
+ * training simulation time.
+ */
+
+ /*
+ * 18. Check the PHY Polarity invert bit
+ */
+ if (invert & COMPHY_POLARITY_TXD_INVERT)
+ reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), phy_txd_inv, 0);
+
+ if (invert & COMPHY_POLARITY_RXD_INVERT)
+ reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), phy_rxd_inv, 0);
+
+ /*
+ * 19. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1
+ * to start PHY power up sequence. All the PHY register
+ * programming should be done before PIN_PU_PLL=1. There should be
+ * no register programming for normal PHY operation from this point.
+ */
+ reg_set(COMPHY_PHY_CFG1_ADDR(lane),
+ rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx,
+ rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx);
+
+ /*
+ * 20. Wait for PHY power up sequence to finish by checking output ports
+ * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1.
+ */
+ ret = comphy_poll_reg(COMPHY_PHY_STAT1_ADDR(lane), /* address */
+ rb_pll_ready_tx | rb_pll_ready_rx, /* value */
+ rb_pll_ready_tx | rb_pll_ready_rx, /* mask */
+ POLL_32B_REG); /* 32bit */
+ if (!ret)
+ printf("Failed to lock PLL for SGMII PHY %d\n", lane);
+
+ /*
+ * 21. Set COMPHY input port PIN_TX_IDLE=0
+ */
+ reg_set(COMPHY_PHY_CFG1_ADDR(lane), 0x0, rb_pin_tx_idle);
+
+ /*
+ * 22. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1.
+ * to start RX initialization. PIN_RX_INIT_DONE will be cleared to
+ * 0 by the PHY. After RX initialization is done, PIN_RX_INIT_DONE
+ * will be set to 1 by COMPHY. Set PIN_RX_INIT=0 after
+ * PIN_RX_INIT_DONE= 1.
+ * Please refer to RX initialization part for details.
+ */
+ reg_set(COMPHY_PHY_CFG1_ADDR(lane), rb_phy_rx_init, 0x0);
+
+ ret = comphy_poll_reg(COMPHY_PHY_STAT1_ADDR(lane), /* address */
+ rb_rx_init_done, /* value */
+ rb_rx_init_done, /* mask */
+ POLL_32B_REG); /* 32bit */
+ if (!ret)
+ printf("Failed to init RX of SGMII PHY %d\n", lane);
+
+ /*
+ * Restore saved selector.
+ */
+ reg_set(COMPHY_SEL_ADDR, saved_selector, 0xFFFFFFFF);
+
+ debug_exit();
+
+ return ret;
+}
+
+void comphy_dedicated_phys_init(void)
+{
+ int node, usb32, ret = 1;
+ const void *blob = gd->fdt_blob;
+
+ debug_enter();
+
+ for (usb32 = 0; usb32 <= 1; usb32++) {
+ /*
+ * There are 2 UTMI PHYs in this SOC.
+ * One is independendent and one is paired with USB3 port (OTG)
+ */
+ if (usb32 == 0) {
+ node = fdt_node_offset_by_compatible(
+ blob, -1, "marvell,armada3700-ehci");
+ } else {
+ node = fdt_node_offset_by_compatible(
+ blob, -1, "marvell,armada3700-xhci");
+ }
+
+ if (node > 0) {
+ if (fdtdec_get_is_enabled(blob, node)) {
+ ret = comphy_usb2_power_up(usb32);
+ if (!ret)
+ printf("Failed to initialize UTMI PHY\n");
+ else
+ debug("UTMI PHY init succeed\n");
+ } else {
+ debug("USB%d node is disabled\n",
+ usb32 == 0 ? 2 : 3);
+ }
+ } else {
+ debug("No USB%d node in DT\n", usb32 == 0 ? 2 : 3);
+ }
+ }
+
+ node = fdt_node_offset_by_compatible(blob, -1,
+ "marvell,armada-8k-sdhci");
+ if (node <= 0) {
+ node = fdt_node_offset_by_compatible(
+ blob, -1, "marvell,armada-3700-sdhci");
+ }
+
+ if (node > 0) {
+ if (fdtdec_get_is_enabled(blob, node)) {
+ ret = comphy_emmc_power_up();
+ if (!ret)
+ printf("Failed to initialize SDIO/eMMC PHY\n");
+ else
+ debug("SDIO/eMMC PHY init succeed\n");
+ } else {
+ debug("SDIO/eMMC node is disabled\n");
+ }
+ } else {
+ debug("No SDIO/eMMC node in DT\n");
+ }
+
+ debug_exit();
+}
+
+int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ struct comphy_map *comphy_map;
+ u32 comphy_max_count = chip_cfg->comphy_lanes_count;
+ u32 lane, ret = 0;
+
+ debug_enter();
+
+ /* Initialize PHY mux */
+ chip_cfg->mux_data = a3700_comphy_mux_data;
+ comphy_mux_init(chip_cfg, serdes_map, COMPHY_SEL_ADDR);
+
+ for (lane = 0, comphy_map = serdes_map; lane < comphy_max_count;
+ lane++, comphy_map++) {
+ debug("Initialize serdes number %d\n", lane);
+ debug("Serdes type = 0x%x invert=%d\n",
+ comphy_map->type, comphy_map->invert);
+
+ switch (comphy_map->type) {
+ case COMPHY_TYPE_UNCONNECTED:
+ continue;
+ break;
+
+ case COMPHY_TYPE_PEX0:
+ ret = comphy_pcie_power_up(comphy_map->speed,
+ comphy_map->invert);
+ break;
+
+ case COMPHY_TYPE_USB3_HOST0:
+ case COMPHY_TYPE_USB3_DEVICE:
+ ret = comphy_usb3_power_up(lane,
+ comphy_map->type,
+ comphy_map->speed,
+ comphy_map->invert);
+ break;
+
+ case COMPHY_TYPE_SGMII0:
+ case COMPHY_TYPE_SGMII1:
+ ret = comphy_sgmii_power_up(lane, comphy_map->speed,
+ comphy_map->invert);
+ break;
+
+ case COMPHY_TYPE_SATA0:
+ ret = comphy_sata_power_up(comphy_map->invert);
+ break;
+
+ default:
+ debug("Unknown SerDes type, skip initialize SerDes %d\n",
+ lane);
+ ret = 1;
+ break;
+ }
+ if (!ret)
+ printf("PLL is not locked - Failed to initialize lane %d\n",
+ lane);
+ }
+
+ debug_exit();
+ return ret;
+}
diff --git a/roms/u-boot/drivers/phy/marvell/comphy_a3700.h b/roms/u-boot/drivers/phy/marvell/comphy_a3700.h
new file mode 100644
index 000000000..8748c6c84
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/comphy_a3700.h
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ */
+
+#ifndef _COMPHY_A3700_H_
+#define _COMPHY_A3700_H_
+
+#include "comphy_core.h"
+
+#define MVEBU_REG(offs) \
+ ((void __iomem *)(ulong)MVEBU_REGISTER(offs))
+
+#define DEFAULT_REFCLK_MHZ 25
+#define PLL_SET_DELAY_US 600
+#define PLL_LOCK_TIMEOUT 1000
+#define POLL_16B_REG 1
+#define POLL_32B_REG 0
+
+/*
+ * COMPHY SB definitions
+ */
+#define COMPHY_SEL_ADDR MVEBU_REG(0x0183FC)
+
+#define COMPHY_PHY_CFG1_ADDR(lane) MVEBU_REG(0x018300 + (1 - lane) * 0x28)
+#define rb_pin_pu_iveref BIT(1)
+#define rb_pin_reset_core BIT(11)
+#define rb_pin_reset_comphy BIT(12)
+#define rb_pin_pu_pll BIT(16)
+#define rb_pin_pu_rx BIT(17)
+#define rb_pin_pu_tx BIT(18)
+#define rb_pin_tx_idle BIT(19)
+#define rf_gen_rx_sel_shift 22
+#define rf_gen_rx_select (0x0F << rf_gen_rx_sel_shift)
+#define rf_gen_tx_sel_shift 26
+#define rf_gen_tx_select (0x0F << rf_gen_tx_sel_shift)
+#define rb_phy_rx_init BIT(30)
+
+#define COMPHY_PHY_STAT1_ADDR(lane) MVEBU_REG(0x018318 + (1 - lane) * 0x28)
+#define rb_rx_init_done BIT(0)
+#define rb_pll_ready_rx BIT(2)
+#define rb_pll_ready_tx BIT(3)
+
+/*
+ * PCIe/USB/SGMII definitions
+ */
+#define PCIE_BASE MVEBU_REG(0x070000)
+#define PCIETOP_BASE MVEBU_REG(0x080000)
+#define PCIE_RAMBASE MVEBU_REG(0x08C000)
+#define PCIEPHY_BASE MVEBU_REG(0x01F000)
+#define PCIEPHY_SHFT 2
+
+#define USB32_BASE MVEBU_REG(0x050000) /* usb3 device */
+#define USB32H_BASE MVEBU_REG(0x058000) /* usb3 host */
+#define USB3PHY_BASE MVEBU_REG(0x05C000)
+#define USB2PHY_BASE MVEBU_REG(0x05D000)
+#define USB2PHY2_BASE MVEBU_REG(0x05F000)
+#define USB32_CTRL_BASE MVEBU_REG(0x05D800)
+#define USB3PHY_SHFT 2
+#define USB3PHY_LANE2_REG_BASE_OFFSET 0x200
+
+static inline void __iomem *sgmiiphy_addr(u32 lane, u32 addr)
+{
+ addr = (addr & 0x00007FF) * 2;
+ if (lane == 1)
+ return PCIEPHY_BASE + addr;
+ else
+ return USB3PHY_BASE + addr;
+}
+
+/* units */
+enum phy_unit {
+ PCIE = 1,
+ USB3 = 2,
+};
+
+static inline void __iomem *phy_addr(enum phy_unit unit, u32 addr)
+{
+ if (unit == PCIE)
+ return PCIEPHY_BASE + addr * PCIEPHY_SHFT;
+ else
+ return USB3PHY_BASE + addr * USB3PHY_SHFT;
+}
+
+/* bit definition for USB32_CTRL_BASE (USB32 Control Mode) */
+#define usb32_ctrl_id_mode BIT(0)
+#define usb32_ctrl_soft_id BIT(1)
+#define usb32_ctrl_int_mode BIT(4)
+
+#define PWR_PLL_CTRL 0x01
+#define rf_phy_mode_shift 5
+#define rf_phy_mode_mask (0x7 << rf_phy_mode_shift)
+#define rf_ref_freq_sel_shift 0
+#define rf_ref_freq_sel_mask (0x1F << rf_ref_freq_sel_shift)
+#define PHY_MODE_SGMII 0x4
+
+#define KVCO_CAL_CTRL 0x02
+#define rb_use_max_pll_rate BIT(12)
+#define rb_force_calibration_done BIT(9)
+
+#define DIG_LB_EN 0x23
+#define rf_data_width_shift 10
+#define rf_data_width_mask (0x3 << rf_data_width_shift)
+
+#define SYNC_PATTERN 0x24
+#define phy_txd_inv BIT(10)
+#define phy_rxd_inv BIT(11)
+
+#define SYNC_MASK_GEN 0x25
+#define rb_idle_sync_en BIT(12)
+
+#define UNIT_CTRL 0x48
+
+#define GEN2_SETTINGS_2 0x3e
+#define g2_tx_ssc_amp BIT(14)
+
+#define GEN2_SETTINGS_3 0x3f
+
+#define GEN3_SETTINGS_3 0x112
+
+#define MISC_REG0 0x4f
+#define rb_clk100m_125m_en BIT(4)
+#define rb_clk500m_en BIT(7)
+#define rb_ref_clk_sel BIT(10)
+
+#define UNIT_IFACE_REF_CLK_CTRL 0x51
+#define rb_ref1m_gen_div_force BIT(8)
+#define rf_ref1m_gen_div_value_shift 0
+#define rf_ref1m_gen_div_value_mask (0xFF << rf_ref1m_gen_div_value_shift)
+
+#define UNIT_ERR_CNT_CONST_CTRL 0x6a
+#define rb_fast_dfe_enable BIT(13)
+
+#define MISC_REG1 0x73
+#define bf_sel_bits_pcie_force BIT(15)
+
+#define LANE_CFG0 0x180
+#define bf_use_max_pll_rate BIT(9)
+
+#define LANE_CFG1 0x181
+#define bf_use_max_pll_rate BIT(9)
+#define prd_txdeemph1_mask BIT(15)
+#define tx_det_rx_mode BIT(6)
+#define gen2_tx_data_dly_deft (2 << 3)
+#define gen2_tx_data_dly_mask (BIT(3) | BIT(4))
+#define tx_elec_idle_mode_en BIT(0)
+
+#define LANE_CFG4 0x188
+#define bf_spread_spectrum_clock_en BIT(7)
+
+#define LANE_STAT1 0x183
+#define rb_txdclk_pclk_en BIT(0)
+
+#define GLOB_PHY_CTRL0 0x1c1
+#define bf_soft_rst BIT(0)
+#define bf_mode_refdiv 0x30
+#define rb_mode_core_clk_freq_sel BIT(9)
+#define rb_mode_pipe_width_32 BIT(3)
+
+#define TEST_MODE_CTRL 0x1c2
+#define rb_mode_margin_override BIT(2)
+
+#define GLOB_CLK_SRC_LO 0x1c3
+#define bf_cfg_sel_20b BIT(15)
+
+#define PWR_MGM_TIM1 0x1d0
+
+#define PCIE_REF_CLK_ADDR (PCIE_BASE + 0x4814)
+
+#define USB3_CTRPUL_VAL_REG (0x20 + USB32_BASE)
+#define USB3H_CTRPUL_VAL_REG (0x3454 + USB32H_BASE)
+#define rb_usb3_ctr_100ns 0xff000000
+
+#define USB2_OTG_PHY_CTRL_ADDR (0x820 + USB2PHY_BASE)
+#define rb_usb2phy_suspm BIT(14)
+#define rb_usb2phy_pu BIT(0)
+
+#define USB2_PHY_OTG_CTRL_ADDR (0x34 + USB2PHY_BASE)
+#define rb_pu_otg BIT(4)
+
+#define USB2_PHY_CHRGR_DET_ADDR (0x38 + USB2PHY_BASE)
+#define rb_cdp_en BIT(2)
+#define rb_dcp_en BIT(3)
+#define rb_pd_en BIT(4)
+#define rb_pu_chrg_dtc BIT(5)
+#define rb_cdp_dm_auto BIT(7)
+#define rb_enswitch_dp BIT(12)
+#define rb_enswitch_dm BIT(13)
+
+#define USB2_CAL_CTRL_ADDR (0x8 + USB2PHY_BASE)
+#define rb_usb2phy_pllcal_done BIT(31)
+#define rb_usb2phy_impcal_done BIT(23)
+
+#define USB2_PLL_CTRL0_ADDR (0x0 + USB2PHY_BASE)
+#define rb_usb2phy_pll_ready BIT(31)
+
+#define USB2_RX_CHAN_CTRL1_ADDR (0x18 + USB2PHY_BASE)
+#define rb_usb2phy_sqcal_done BIT(31)
+
+#define USB2_PHY2_CTRL_ADDR (0x804 + USB2PHY2_BASE)
+#define rb_usb2phy2_suspm BIT(7)
+#define rb_usb2phy2_pu BIT(0)
+#define USB2_PHY2_CAL_CTRL_ADDR (0x8 + USB2PHY2_BASE)
+#define USB2_PHY2_PLL_CTRL0_ADDR (0x0 + USB2PHY2_BASE)
+#define USB2_PHY2_RX_CHAN_CTRL1_ADDR (0x18 + USB2PHY2_BASE)
+
+#define USB2_PHY_BASE(usb32) (usb32 == 0 ? USB2PHY2_BASE : USB2PHY_BASE)
+#define USB2_PHY_CTRL_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_CTRL_ADDR : USB2_OTG_PHY_CTRL_ADDR)
+#define RB_USB2PHY_SUSPM(usb32) \
+ (usb32 == 0 ? rb_usb2phy2_suspm : rb_usb2phy_suspm)
+#define RB_USB2PHY_PU(usb32) \
+ (usb32 == 0 ? rb_usb2phy2_pu : rb_usb2phy_pu)
+#define USB2_PHY_CAL_CTRL_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_CAL_CTRL_ADDR : USB2_CAL_CTRL_ADDR)
+#define USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_RX_CHAN_CTRL1_ADDR : USB2_RX_CHAN_CTRL1_ADDR)
+#define USB2_PHY_PLL_CTRL0_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_PLL_CTRL0_ADDR : USB2_PLL_CTRL0_ADDR)
+
+/*
+ * SATA definitions
+ */
+#define AHCI_BASE MVEBU_REG(0xE0000)
+
+#define rh_vsreg_addr (AHCI_BASE + 0x178)
+#define rh_vsreg_data (AHCI_BASE + 0x17C)
+#define rh_vs0_a (AHCI_BASE + 0xA0)
+#define rh_vs0_d (AHCI_BASE + 0xA4)
+
+#define vphy_sync_pattern_reg 0x224
+#define bs_txd_inv BIT(10)
+#define bs_rxd_inv BIT(11)
+
+#define vphy_loopback_reg0 0x223
+#define bs_phyintf_40bit 0x0C00
+#define bs_pll_ready_tx 0x10
+
+#define vphy_power_reg0 0x201
+
+#define vphy_calctl_reg 0x202
+#define bs_max_pll_rate BIT(12)
+
+#define vphy_reserve_reg 0x0e
+#define bs_phyctrl_frm_pin BIT(13)
+
+#define vsata_ctrl_reg 0x00
+#define bs_phy_pu_pll BIT(6)
+
+/*
+ * SDIO/eMMC definitions
+ */
+#define SDIO_BASE MVEBU_REG(0xD8000)
+
+#define SDIO_HOST_CTRL1_ADDR (SDIO_BASE + 0x28)
+#define SDIO_SDHC_FIFO_ADDR (SDIO_BASE + 0x12C)
+#define SDIO_CAP_12_ADDR (SDIO_BASE + 0x40)
+#define SDIO_ENDIAN_ADDR (SDIO_BASE + 0x1A4)
+#define SDIO_PHY_TIMING_ADDR (SDIO_BASE + 0x170)
+#define SDIO_PHY_PAD_CTRL0_ADDR (SDIO_BASE + 0x178)
+#define SDIO_DLL_RST_ADDR (SDIO_BASE + 0x148)
+
+#endif /* _COMPHY_A3700_H_ */
diff --git a/roms/u-boot/drivers/phy/marvell/comphy_core.c b/roms/u-boot/drivers/phy/marvell/comphy_core.c
new file mode 100644
index 000000000..2c9d7b228
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/comphy_core.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/libfdt.h>
+
+#include "comphy_core.h"
+
+#define COMPHY_MAX_CHIP 4
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char *get_speed_string(u32 speed)
+{
+ static const char * const speed_strings[] = {
+ "1.25 Gbps", "2.5 Gbps", "3.125 Gbps",
+ "5 Gbps", "5.125 Gpbs", "6 Gbps",
+ "10.3125 Gbps"
+ };
+
+ if (speed < 0 || speed > COMPHY_SPEED_MAX)
+ return "invalid";
+
+ return speed_strings[speed];
+}
+
+static const char *get_type_string(u32 type)
+{
+ static const char * const type_strings[] = {
+ "UNCONNECTED", "PEX0", "PEX1", "PEX2", "PEX3",
+ "SATA0", "SATA1", "SGMII0", "SGMII1", "SGMII2",
+ "USB3", "USB3_HOST0", "USB3_HOST1",
+ "USB3_DEVICE", "RXAUI0", "RXAUI1", "SFI0", "SFI1", "AP",
+ "IGNORE"
+ };
+
+ if (type < 0 || type > COMPHY_TYPE_MAX)
+ return "invalid";
+
+ return type_strings[type];
+}
+
+void comphy_print(struct chip_serdes_phy_config *chip_cfg,
+ struct comphy_map *comphy_map_data)
+{
+ u32 lane;
+
+ for (lane = 0; lane < chip_cfg->comphy_lanes_count;
+ lane++, comphy_map_data++) {
+ if (comphy_map_data->speed == COMPHY_SPEED_INVALID) {
+ printf("Comphy-%d: %-13s\n", lane,
+ get_type_string(comphy_map_data->type));
+ } else {
+ printf("Comphy-%d: %-13s %-10s\n", lane,
+ get_type_string(comphy_map_data->type),
+ get_speed_string(comphy_map_data->speed));
+ }
+ }
+}
+
+int comphy_rx_training(struct udevice *dev, u32 lane)
+{
+ struct chip_serdes_phy_config *chip_cfg = dev_get_priv(dev);
+
+ if (chip_cfg->rx_training)
+ return chip_cfg->rx_training(chip_cfg, lane);
+
+ return 0;
+}
+
+__weak int comphy_update_map(struct comphy_map *serdes_map, int count)
+{
+ return 0;
+}
+
+static int comphy_probe(struct udevice *dev)
+{
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ struct chip_serdes_phy_config *chip_cfg = dev_get_priv(dev);
+ int subnode;
+ int lane;
+ int last_idx = 0;
+ static int current_idx;
+ int res;
+
+ /* Save base addresses for later use */
+ chip_cfg->comphy_base_addr = (void *)devfdt_get_addr_index(dev, 0);
+ if (IS_ERR(chip_cfg->comphy_base_addr))
+ return PTR_ERR(chip_cfg->comphy_base_addr);
+
+ chip_cfg->hpipe3_base_addr = (void *)devfdt_get_addr_index(dev, 1);
+ if (IS_ERR(chip_cfg->hpipe3_base_addr))
+ return PTR_ERR(chip_cfg->hpipe3_base_addr);
+
+ chip_cfg->comphy_lanes_count = fdtdec_get_int(blob, node,
+ "max-lanes", 0);
+ if (chip_cfg->comphy_lanes_count <= 0) {
+ dev_err(dev, "comphy max lanes is wrong\n");
+ return -EINVAL;
+ }
+
+ chip_cfg->comphy_mux_bitcount = fdtdec_get_int(blob, node,
+ "mux-bitcount", 0);
+ if (chip_cfg->comphy_mux_bitcount <= 0) {
+ dev_err(dev, "comphy mux bit count is wrong\n");
+ return -EINVAL;
+ }
+
+ chip_cfg->comphy_mux_lane_order =
+ fdtdec_locate_array(blob, node, "mux-lane-order",
+ chip_cfg->comphy_lanes_count);
+
+ if (device_is_compatible(dev, "marvell,comphy-armada-3700")) {
+ chip_cfg->ptr_comphy_chip_init = comphy_a3700_init;
+ chip_cfg->rx_training = NULL;
+ }
+
+ if (device_is_compatible(dev, "marvell,comphy-cp110")) {
+ chip_cfg->ptr_comphy_chip_init = comphy_cp110_init;
+ chip_cfg->rx_training = comphy_cp110_sfi_rx_training;
+ }
+
+ /*
+ * Bail out if no chip_init function is defined, e.g. no
+ * compatible node is found
+ */
+ if (!chip_cfg->ptr_comphy_chip_init) {
+ dev_err(dev, "comphy: No compatible DT node found\n");
+ return -ENODEV;
+ }
+
+ lane = 0;
+ fdt_for_each_subnode(subnode, blob, node) {
+ /* Skip disabled ports */
+ if (!fdtdec_get_is_enabled(blob, subnode))
+ continue;
+
+ chip_cfg->comphy_map_data[lane].type =
+ fdtdec_get_int(blob, subnode, "phy-type",
+ COMPHY_TYPE_INVALID);
+
+ if (chip_cfg->comphy_map_data[lane].type ==
+ COMPHY_TYPE_INVALID) {
+ printf("no phy type for lane %d, setting lane as unconnected\n",
+ lane + 1);
+ continue;
+ }
+
+ chip_cfg->comphy_map_data[lane].speed =
+ fdtdec_get_int(blob, subnode, "phy-speed",
+ COMPHY_SPEED_INVALID);
+
+ chip_cfg->comphy_map_data[lane].invert =
+ fdtdec_get_int(blob, subnode, "phy-invert",
+ COMPHY_POLARITY_NO_INVERT);
+
+ chip_cfg->comphy_map_data[lane].clk_src =
+ fdtdec_get_bool(blob, subnode, "clk-src");
+
+ chip_cfg->comphy_map_data[lane].end_point =
+ fdtdec_get_bool(blob, subnode, "end_point");
+
+ lane++;
+ }
+
+ res = comphy_update_map(chip_cfg->comphy_map_data, chip_cfg->comphy_lanes_count);
+ if (res < 0)
+ return res;
+
+ /* Save CP index for MultiCP devices (A8K) */
+ chip_cfg->cp_index = current_idx++;
+ /* PHY power UP sequence */
+ chip_cfg->ptr_comphy_chip_init(chip_cfg, chip_cfg->comphy_map_data);
+ /* PHY print SerDes status */
+ printf("Comphy chip #%d:\n", chip_cfg->cp_index);
+ comphy_print(chip_cfg, chip_cfg->comphy_map_data);
+
+ /*
+ * Only run the dedicated PHY init code once, in the last PHY init call
+ */
+ if (of_machine_is_compatible("marvell,armada8040"))
+ last_idx = 1;
+
+ if (chip_cfg->cp_index == last_idx) {
+ /* Initialize dedicated PHYs (not muxed SerDes lanes) */
+ comphy_dedicated_phys_init();
+ }
+
+ return 0;
+}
+
+static const struct udevice_id comphy_ids[] = {
+ { .compatible = "marvell,mvebu-comphy" },
+ { }
+};
+
+U_BOOT_DRIVER(mvebu_comphy) = {
+ .name = "mvebu_comphy",
+ .id = UCLASS_MISC,
+ .of_match = comphy_ids,
+ .probe = comphy_probe,
+ .priv_auto = sizeof(struct chip_serdes_phy_config),
+};
diff --git a/roms/u-boot/drivers/phy/marvell/comphy_core.h b/roms/u-boot/drivers/phy/marvell/comphy_core.h
new file mode 100644
index 000000000..ba64491df
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/comphy_core.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ */
+
+#ifndef _COMPHY_CORE_H_
+#define _COMPHY_CORE_H_
+
+#include <fdtdec.h>
+#include <mvebu/comphy.h>
+
+#if defined(DEBUG)
+#define debug_enter() printf("----> Enter %s\n", __func__);
+#define debug_exit() printf("<---- Exit %s\n", __func__);
+#else
+#define debug_enter()
+#define debug_exit()
+#endif
+
+#define MAX_LANE_OPTIONS 10
+#define MAX_UTMI_PHY_COUNT 6
+
+struct comphy_mux_options {
+ u32 type;
+ u32 mux_value;
+};
+
+struct comphy_mux_data {
+ u32 max_lane_values;
+ struct comphy_mux_options mux_values[MAX_LANE_OPTIONS];
+};
+
+struct chip_serdes_phy_config {
+ struct comphy_mux_data *mux_data;
+ int (*ptr_comphy_chip_init)(struct chip_serdes_phy_config *,
+ struct comphy_map *);
+ int (*rx_training)(struct chip_serdes_phy_config *, u32);
+ void __iomem *comphy_base_addr;
+ void __iomem *hpipe3_base_addr;
+ u32 comphy_lanes_count;
+ u32 comphy_mux_bitcount;
+ const fdt32_t *comphy_mux_lane_order;
+ u32 cp_index;
+ struct comphy_map comphy_map_data[MAX_LANE_OPTIONS];
+};
+
+/* Register helper functions */
+static inline void reg_set_silent(void __iomem *addr, u32 data, u32 mask)
+{
+ u32 reg_data;
+
+ reg_data = readl(addr);
+ reg_data &= ~mask;
+ reg_data |= data;
+ writel(reg_data, addr);
+}
+
+static inline void reg_set(void __iomem *addr, u32 data, u32 mask)
+{
+ debug("Write to address = %#010lx, data = %#010x (mask = %#010x) - ",
+ (unsigned long)addr, data, mask);
+ debug("old value = %#010x ==> ", readl(addr));
+ reg_set_silent(addr, data, mask);
+ debug("new value %#010x\n", readl(addr));
+}
+
+static inline void reg_set_silent16(void __iomem *addr, u16 data, u16 mask)
+{
+ u16 reg_data;
+
+ reg_data = readw(addr);
+ reg_data &= ~mask;
+ reg_data |= data;
+ writew(reg_data, addr);
+}
+
+static inline void reg_set16(void __iomem *addr, u16 data, u16 mask)
+{
+ debug("Write to address = %#010lx, data = %#06x (mask = %#06x) - ",
+ (unsigned long)addr, data, mask);
+ debug("old value = %#06x ==> ", readw(addr));
+ reg_set_silent16(addr, data, mask);
+ debug("new value %#06x\n", readw(addr));
+}
+
+/* SoC specific init functions */
+#ifdef CONFIG_ARMADA_3700
+int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map);
+#else
+static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ /*
+ * This function should never be called in this configuration, so
+ * lets return an error here.
+ */
+ return -1;
+}
+#endif
+
+#ifdef CONFIG_ARMADA_8K
+int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map);
+int comphy_cp110_sfi_rx_training(struct chip_serdes_phy_config *ptr_chip_cfg,
+ u32 lane);
+#else
+static inline int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ /*
+ * This function should never be called in this configuration, so
+ * lets return an error here.
+ */
+ return -1;
+}
+
+static inline int comphy_cp110_sfi_rx_training(
+ struct chip_serdes_phy_config *ptr_chip_cfg,
+ u32 lane)
+{
+ /*
+ * This function should never be called in this configuration, so
+ * lets return an error here.
+ */
+ return -1;
+}
+#endif
+
+void comphy_dedicated_phys_init(void);
+
+/* MUX function */
+void comphy_mux_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *comphy_map_data,
+ void __iomem *selector_base);
+
+void comphy_pcie_config_set(u32 comphy_max_count,
+ struct comphy_map *serdes_map);
+void comphy_pcie_config_detect(u32 comphy_max_count,
+ struct comphy_map *serdes_map);
+void comphy_pcie_unit_general_config(u32 pex_index);
+
+#endif /* _COMPHY_CORE_H_ */
+
diff --git a/roms/u-boot/drivers/phy/marvell/comphy_cp110.c b/roms/u-boot/drivers/phy/marvell/comphy_cp110.c
new file mode 100644
index 000000000..418318d12
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/comphy_cp110.c
@@ -0,0 +1,681 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <linux/delay.h>
+
+#include "comphy_core.h"
+#include "sata.h"
+#include "utmi_phy.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Firmware related definitions used for SMC calls */
+#define MV_SIP_COMPHY_POWER_ON 0x82000001
+#define MV_SIP_COMPHY_POWER_OFF 0x82000002
+#define MV_SIP_COMPHY_PLL_LOCK 0x82000003
+#define MV_SIP_COMPHY_XFI_TRAIN 0x82000004
+
+/* Used to distinguish between different possible callers (U-boot/Linux) */
+#define COMPHY_CALLER_UBOOT (0x1 << 21)
+
+#define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12)
+#define COMPHY_FW_FORMAT(mode, idx, speeds) \
+ (((mode) << 12) | ((idx) << 8) | ((speeds) << 2))
+
+#define COMPHY_FW_PCIE_FORMAT(pcie_width, clk_src, mode, speeds) \
+ (COMPHY_CALLER_UBOOT | ((pcie_width) << 18) | \
+ ((clk_src) << 17) | COMPHY_FW_FORMAT(mode, 0, speeds))
+
+#define COMPHY_SATA_MODE 0x1
+#define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */
+#define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */
+#define COMPHY_USB3H_MODE 0x4
+#define COMPHY_USB3D_MODE 0x5
+#define COMPHY_PCIE_MODE 0x6
+#define COMPHY_RXAUI_MODE 0x7
+#define COMPHY_XFI_MODE 0x8
+#define COMPHY_SFI_MODE 0x9
+#define COMPHY_USB3_MODE 0xa
+#define COMPHY_AP_MODE 0xb
+
+/* Comphy unit index macro */
+#define COMPHY_UNIT_ID0 0
+#define COMPHY_UNIT_ID1 1
+#define COMPHY_UNIT_ID2 2
+#define COMPHY_UNIT_ID3 3
+
+struct utmi_phy_data {
+ void __iomem *utmi_pll_addr;
+ void __iomem *utmi_base_addr;
+ void __iomem *usb_cfg_addr;
+ void __iomem *utmi_cfg_addr;
+ u32 utmi_phy_port;
+};
+
+static u32 polling_with_timeout(void __iomem *addr, u32 val,
+ u32 mask, unsigned long usec_timout)
+{
+ u32 data;
+
+ do {
+ udelay(1);
+ data = readl(addr) & mask;
+ } while (data != val && --usec_timout > 0);
+
+ if (usec_timout == 0)
+ return data;
+
+ return 0;
+}
+
+static int comphy_smc(u32 function_id, void __iomem *comphy_base_addr,
+ u32 lane, u32 mode)
+{
+ struct pt_regs pregs = {0};
+
+ pregs.regs[0] = function_id;
+ pregs.regs[1] = (unsigned long)comphy_base_addr;
+ pregs.regs[2] = lane;
+ pregs.regs[3] = mode;
+
+ smc_call(&pregs);
+
+ /*
+ * TODO: Firmware return 0 on success, temporary map it to u-boot
+ * convention, but after all comphy will be reworked the convention in
+ * u-boot should be change and this conversion removed
+ */
+ return pregs.regs[0] ? 0 : 1;
+}
+
+/* This function performs RX training for all FFE possible values.
+ * We get the result for each FFE and eventually the best FFE will
+ * be used and set to the HW.
+ *
+ * Return '1' on succsess.
+ * Return '0' on failure.
+ */
+int comphy_cp110_sfi_rx_training(struct chip_serdes_phy_config *ptr_chip_cfg,
+ u32 lane)
+{
+ int ret;
+ u32 type = ptr_chip_cfg->comphy_map_data[lane].type;
+
+ debug_enter();
+
+ if (type != COMPHY_TYPE_SFI0 && type != COMPHY_TYPE_SFI1) {
+ pr_err("Comphy %d isn't configured to SFI\n", lane);
+ return 0;
+ }
+
+ /* Mode is not relevant for xfi training */
+ ret = comphy_smc(MV_SIP_COMPHY_XFI_TRAIN,
+ ptr_chip_cfg->comphy_base_addr, lane, 0);
+
+ debug_exit();
+
+ return ret;
+}
+
+static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base,
+ void __iomem *comphy_base_addr, int cp_index,
+ u32 type)
+{
+ u32 mask, data, i, ret = 1;
+ void __iomem *sata_base = NULL;
+ int sata_node = -1; /* Set to -1 in order to read the first sata node */
+
+ debug_enter();
+
+ /*
+ * Assumption - each CP has only one SATA controller
+ * Calling fdt_node_offset_by_compatible first time (with sata_node = -1
+ * will return the first node always.
+ * In order to parse each CPs SATA node, fdt_node_offset_by_compatible
+ * must be called again (according to the CP id)
+ */
+ for (i = 0; i < (cp_index + 1); i++)
+ sata_node = fdt_node_offset_by_compatible(
+ gd->fdt_blob, sata_node, "marvell,armada-8k-ahci");
+
+ if (sata_node == 0) {
+ pr_err("SATA node not found in FDT\n");
+ return 0;
+ }
+
+ sata_base = (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, sata_node, "reg", 0, NULL, true);
+ if (sata_base == NULL) {
+ pr_err("SATA address not found in FDT\n");
+ return 0;
+ }
+
+ debug("SATA address found in FDT %p\n", sata_base);
+
+ debug("stage: MAC configuration - power down comphy\n");
+ /*
+ * MAC configuration powe down comphy use indirect address for
+ * vendor spesific SATA control register
+ */
+ reg_set(sata_base + SATA3_VENDOR_ADDRESS,
+ SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET,
+ SATA3_VENDOR_ADDR_MASK);
+ /* SATA 0 power down */
+ mask = SATA3_CTRL_SATA0_PD_MASK;
+ data = 0x1 << SATA3_CTRL_SATA0_PD_OFFSET;
+ /* SATA 1 power down */
+ mask |= SATA3_CTRL_SATA1_PD_MASK;
+ data |= 0x1 << SATA3_CTRL_SATA1_PD_OFFSET;
+ /* SATA SSU disable */
+ mask |= SATA3_CTRL_SATA1_ENABLE_MASK;
+ data |= 0x0 << SATA3_CTRL_SATA1_ENABLE_OFFSET;
+ /* SATA port 1 disable */
+ mask |= SATA3_CTRL_SATA_SSU_MASK;
+ data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET;
+ reg_set(sata_base + SATA3_VENDOR_DATA, data, mask);
+
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, comphy_base_addr, lane, type);
+
+ /*
+ * MAC configuration power up comphy - power up PLL/TX/RX
+ * use indirect address for vendor spesific SATA control register
+ */
+ reg_set(sata_base + SATA3_VENDOR_ADDRESS,
+ SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET,
+ SATA3_VENDOR_ADDR_MASK);
+ /* SATA 0 power up */
+ mask = SATA3_CTRL_SATA0_PD_MASK;
+ data = 0x0 << SATA3_CTRL_SATA0_PD_OFFSET;
+ /* SATA 1 power up */
+ mask |= SATA3_CTRL_SATA1_PD_MASK;
+ data |= 0x0 << SATA3_CTRL_SATA1_PD_OFFSET;
+ /* SATA SSU enable */
+ mask |= SATA3_CTRL_SATA1_ENABLE_MASK;
+ data |= 0x1 << SATA3_CTRL_SATA1_ENABLE_OFFSET;
+ /* SATA port 1 enable */
+ mask |= SATA3_CTRL_SATA_SSU_MASK;
+ data |= 0x1 << SATA3_CTRL_SATA_SSU_OFFSET;
+ reg_set(sata_base + SATA3_VENDOR_DATA, data, mask);
+
+ /* MBUS request size and interface select register */
+ reg_set(sata_base + SATA3_VENDOR_ADDRESS,
+ SATA_MBUS_SIZE_SELECT_REG << SATA3_VENDOR_ADDR_OFSSET,
+ SATA3_VENDOR_ADDR_MASK);
+ /* Mbus regret enable */
+ reg_set(sata_base + SATA3_VENDOR_DATA,
+ 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK);
+
+ ret = comphy_smc(MV_SIP_COMPHY_PLL_LOCK, comphy_base_addr, lane, type);
+
+ debug_exit();
+ return ret;
+}
+
+static void comphy_utmi_power_down(u32 utmi_index, void __iomem *utmi_base_addr,
+ void __iomem *usb_cfg_addr,
+ void __iomem *utmi_cfg_addr,
+ u32 utmi_phy_port)
+{
+ u32 mask, data;
+
+ debug_enter();
+ debug("stage: UTMI %d - Power down transceiver (power down Phy), Power down PLL, and SuspendDM\n",
+ utmi_index);
+ /* Power down UTMI PHY */
+ reg_set(utmi_cfg_addr, 0x0 << UTMI_PHY_CFG_PU_OFFSET,
+ UTMI_PHY_CFG_PU_MASK);
+
+ /*
+ * If UTMI connected to USB Device, configure mux prior to PHY init
+ * (Device can be connected to UTMI0 or to UTMI1)
+ */
+ if (utmi_phy_port == UTMI_PHY_TO_USB3_DEVICE0) {
+ debug("stage: UTMI %d - Enable Device mode and configure UTMI mux\n",
+ utmi_index);
+ /* USB3 Device UTMI enable */
+ mask = UTMI_USB_CFG_DEVICE_EN_MASK;
+ data = 0x1 << UTMI_USB_CFG_DEVICE_EN_OFFSET;
+ /* USB3 Device UTMI MUX */
+ mask |= UTMI_USB_CFG_DEVICE_MUX_MASK;
+ data |= utmi_index << UTMI_USB_CFG_DEVICE_MUX_OFFSET;
+ reg_set(usb_cfg_addr, data, mask);
+ }
+
+ /* Set Test suspendm mode */
+ mask = UTMI_CTRL_STATUS0_SUSPENDM_MASK;
+ data = 0x1 << UTMI_CTRL_STATUS0_SUSPENDM_OFFSET;
+ /* Enable Test UTMI select */
+ mask |= UTMI_CTRL_STATUS0_TEST_SEL_MASK;
+ data |= 0x1 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET;
+ reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG, data, mask);
+
+ /* Wait for UTMI power down */
+ mdelay(1);
+
+ debug_exit();
+ return;
+}
+
+static void comphy_utmi_phy_config(u32 utmi_index, void __iomem *utmi_pll_addr,
+ void __iomem *utmi_base_addr,
+ void __iomem *usb_cfg_addr,
+ void __iomem *utmi_cfg_addr,
+ u32 utmi_phy_port)
+{
+ u32 mask, data;
+
+ debug_exit();
+ debug("stage: Configure UTMI PHY %d registers\n", utmi_index);
+ /* Reference Clock Divider Select */
+ mask = UTMI_PLL_CTRL_REFDIV_MASK;
+ data = 0x5 << UTMI_PLL_CTRL_REFDIV_OFFSET;
+ /* Feedback Clock Divider Select - 90 for 25Mhz*/
+ mask |= UTMI_PLL_CTRL_FBDIV_MASK;
+ data |= 0x60 << UTMI_PLL_CTRL_FBDIV_OFFSET;
+ /* Select LPFR - 0x0 for 25Mhz/5=5Mhz*/
+ mask |= UTMI_PLL_CTRL_SEL_LPFR_MASK;
+ data |= 0x0 << UTMI_PLL_CTRL_SEL_LPFR_OFFSET;
+ reg_set(utmi_pll_addr + UTMI_PLL_CTRL_REG, data, mask);
+
+ /* Impedance Calibration Threshold Setting */
+ mask = UTMI_CALIB_CTRL_IMPCAL_VTH_MASK;
+ data = 0x7 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET;
+ reg_set(utmi_pll_addr + UTMI_CALIB_CTRL_REG, data, mask);
+
+ /* Start Impedance and PLL Calibration */
+ mask = UTMI_CALIB_CTRL_PLLCAL_START_MASK;
+ data = (0x1 << UTMI_CALIB_CTRL_PLLCAL_START_OFFSET);
+ mask |= UTMI_CALIB_CTRL_IMPCAL_START_MASK;
+ data |= (0x1 << UTMI_CALIB_CTRL_IMPCAL_START_OFFSET);
+ reg_set(utmi_pll_addr + UTMI_CALIB_CTRL_REG, data, mask);
+
+ /* Set LS TX driver strength coarse control */
+ mask = UTMI_TX_CH_CTRL_AMP_MASK;
+ data = 0x4 << UTMI_TX_CH_CTRL_AMP_OFFSET;
+ mask |= UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK;
+ data |= 0x3 << UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET;
+ mask |= UTMI_TX_CH_CTRL_DRV_EN_LS_MASK;
+ data |= 0x3 << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET;
+ reg_set(utmi_base_addr + UTMI_TX_CH_CTRL_REG, data, mask);
+
+ /* Enable SQ */
+ mask = UTMI_RX_CH_CTRL0_SQ_DET_MASK;
+ data = 0x1 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET;
+ /* Enable analog squelch detect */
+ mask |= UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK;
+ data |= 0x0 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET;
+ mask |= UTMI_RX_CH_CTRL0_DISCON_THRESH_MASK;
+ data |= 0x0 << UTMI_RX_CH_CTRL0_DISCON_THRESH_OFFSET;
+ reg_set(utmi_base_addr + UTMI_RX_CH_CTRL0_REG, data, mask);
+
+ /* Set External squelch calibration number */
+ mask = UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK;
+ data = 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET;
+ /* Enable the External squelch calibration */
+ mask |= UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_MASK;
+ data |= 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET;
+ reg_set(utmi_base_addr + UTMI_RX_CH_CTRL1_REG, data, mask);
+
+ /* Set Control VDAT Reference Voltage - 0.325V */
+ mask = UTMI_CHGDTC_CTRL_VDAT_MASK;
+ data = 0x1 << UTMI_CHGDTC_CTRL_VDAT_OFFSET;
+ /* Set Control VSRC Reference Voltage - 0.6V */
+ mask |= UTMI_CHGDTC_CTRL_VSRC_MASK;
+ data |= 0x1 << UTMI_CHGDTC_CTRL_VSRC_OFFSET;
+ reg_set(utmi_base_addr + UTMI_CHGDTC_CTRL_REG, data, mask);
+
+ debug_exit();
+ return;
+}
+
+static int comphy_utmi_power_up(u32 utmi_index, void __iomem *utmi_pll_addr,
+ void __iomem *utmi_base_addr,
+ void __iomem *usb_cfg_addr,
+ void __iomem *utmi_cfg_addr, u32 utmi_phy_port)
+{
+ u32 data, mask, ret = 1;
+ void __iomem *addr;
+
+ debug_enter();
+ debug("stage: UTMI %d - Power up transceiver(Power up Phy), and exit SuspendDM\n",
+ utmi_index);
+ /* Power UP UTMI PHY */
+ reg_set(utmi_cfg_addr, 0x1 << UTMI_PHY_CFG_PU_OFFSET,
+ UTMI_PHY_CFG_PU_MASK);
+ /* Disable Test UTMI select */
+ reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG,
+ 0x0 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET,
+ UTMI_CTRL_STATUS0_TEST_SEL_MASK);
+
+ debug("stage: Polling for PLL and impedance calibration done, and PLL ready done\n");
+ addr = utmi_pll_addr + UTMI_CALIB_CTRL_REG;
+ data = UTMI_CALIB_CTRL_IMPCAL_DONE_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ pr_err("Impedance calibration is not done\n");
+ debug("Read from reg = %p - value = 0x%x\n", addr, data);
+ ret = 0;
+ }
+
+ data = UTMI_CALIB_CTRL_PLLCAL_DONE_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ pr_err("PLL calibration is not done\n");
+ debug("Read from reg = %p - value = 0x%x\n", addr, data);
+ ret = 0;
+ }
+
+ addr = utmi_pll_addr + UTMI_PLL_CTRL_REG;
+ data = UTMI_PLL_CTRL_PLL_RDY_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ pr_err("PLL is not ready\n");
+ debug("Read from reg = %p - value = 0x%x\n", addr, data);
+ ret = 0;
+ }
+
+ if (ret)
+ debug("Passed\n");
+ else
+ debug("\n");
+
+ debug_exit();
+ return ret;
+}
+
+/*
+ * comphy_utmi_phy_init initialize the UTMI PHY
+ * the init split in 3 parts:
+ * 1. Power down transceiver and PLL
+ * 2. UTMI PHY configure
+ * 3. Power up transceiver and PLL
+ * Note: - Power down/up should be once for both UTMI PHYs
+ * - comphy_dedicated_phys_init call this function if at least there is
+ * one UTMI PHY exists in FDT blob. access to cp110_utmi_data[0] is
+ * legal
+ */
+static void comphy_utmi_phy_init(u32 utmi_phy_count,
+ struct utmi_phy_data *cp110_utmi_data)
+{
+ u32 i;
+
+ debug_enter();
+ /* UTMI Power down */
+ for (i = 0; i < utmi_phy_count; i++) {
+ comphy_utmi_power_down(i, cp110_utmi_data[i].utmi_base_addr,
+ cp110_utmi_data[i].usb_cfg_addr,
+ cp110_utmi_data[i].utmi_cfg_addr,
+ cp110_utmi_data[i].utmi_phy_port);
+ }
+ /* PLL Power down */
+ debug("stage: UTMI PHY power down PLL\n");
+ for (i = 0; i < utmi_phy_count; i++) {
+ reg_set(cp110_utmi_data[i].usb_cfg_addr,
+ 0x0 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK);
+ }
+ /* UTMI configure */
+ for (i = 0; i < utmi_phy_count; i++) {
+ comphy_utmi_phy_config(i, cp110_utmi_data[i].utmi_pll_addr,
+ cp110_utmi_data[i].utmi_base_addr,
+ cp110_utmi_data[i].usb_cfg_addr,
+ cp110_utmi_data[i].utmi_cfg_addr,
+ cp110_utmi_data[i].utmi_phy_port);
+ }
+ /* UTMI Power up */
+ for (i = 0; i < utmi_phy_count; i++) {
+ if (!comphy_utmi_power_up(i, cp110_utmi_data[i].utmi_pll_addr,
+ cp110_utmi_data[i].utmi_base_addr,
+ cp110_utmi_data[i].usb_cfg_addr,
+ cp110_utmi_data[i].utmi_cfg_addr,
+ cp110_utmi_data[i].utmi_phy_port)) {
+ pr_err("Failed to initialize UTMI PHY %d\n", i);
+ continue;
+ }
+ printf("UTMI PHY %d initialized to ", i);
+ if (cp110_utmi_data[i].utmi_phy_port ==
+ UTMI_PHY_TO_USB3_DEVICE0)
+ printf("USB Device\n");
+ else
+ printf("USB Host%d\n",
+ cp110_utmi_data[i].utmi_phy_port);
+ }
+ /* PLL Power up */
+ debug("stage: UTMI PHY power up PLL\n");
+ for (i = 0; i < utmi_phy_count; i++) {
+ reg_set(cp110_utmi_data[i].usb_cfg_addr,
+ 0x1 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK);
+ }
+
+ debug_exit();
+ return;
+}
+
+/*
+ * comphy_dedicated_phys_init initialize the dedicated PHYs
+ * - not muxed SerDes lanes e.g. UTMI PHY
+ */
+void comphy_dedicated_phys_init(void)
+{
+ struct utmi_phy_data cp110_utmi_data[MAX_UTMI_PHY_COUNT];
+ int node = -1;
+ int node_idx;
+ int parent = -1;
+
+ debug_enter();
+ debug("Initialize USB UTMI PHYs\n");
+
+ for (node_idx = 0; node_idx < MAX_UTMI_PHY_COUNT;) {
+ /* Find the UTMI phy node in device tree */
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, node,
+ "marvell,mvebu-utmi-2.6.0");
+ if (node <= 0)
+ break;
+
+ /* check if node is enabled */
+ if (!fdtdec_get_is_enabled(gd->fdt_blob, node))
+ continue;
+
+ parent = fdt_parent_offset(gd->fdt_blob, node);
+ if (parent <= 0)
+ break;
+
+ /* get base address of UTMI PLL */
+ cp110_utmi_data[node_idx].utmi_pll_addr =
+ (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, parent, "reg", 0, NULL, true);
+ if (!cp110_utmi_data[node_idx].utmi_pll_addr) {
+ pr_err("UTMI PHY PLL address is invalid\n");
+ continue;
+ }
+
+ /* get base address of UTMI phy */
+ cp110_utmi_data[node_idx].utmi_base_addr =
+ (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, node, "reg", 0, NULL, true);
+ if (!cp110_utmi_data[node_idx].utmi_base_addr) {
+ pr_err("UTMI PHY base address is invalid\n");
+ continue;
+ }
+
+ /* get usb config address */
+ cp110_utmi_data[node_idx].usb_cfg_addr =
+ (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, node, "reg", 1, NULL, true);
+ if (!cp110_utmi_data[node_idx].usb_cfg_addr) {
+ pr_err("UTMI PHY base address is invalid\n");
+ continue;
+ }
+
+ /* get UTMI config address */
+ cp110_utmi_data[node_idx].utmi_cfg_addr =
+ (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, node, "reg", 2, NULL, true);
+ if (!cp110_utmi_data[node_idx].utmi_cfg_addr) {
+ pr_err("UTMI PHY base address is invalid\n");
+ continue;
+ }
+
+ /*
+ * get the port number (to check if the utmi connected to
+ * host/device)
+ */
+ cp110_utmi_data[node_idx].utmi_phy_port = fdtdec_get_int(
+ gd->fdt_blob, node, "utmi-port", UTMI_PHY_INVALID);
+ if (cp110_utmi_data[node_idx].utmi_phy_port ==
+ UTMI_PHY_INVALID) {
+ pr_err("UTMI PHY port type is invalid\n");
+ continue;
+ }
+
+ /* count valid UTMI unit */
+ node_idx++;
+ }
+
+ if (node_idx > 0)
+ comphy_utmi_phy_init(node_idx, cp110_utmi_data);
+
+ debug_exit();
+}
+
+int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ struct comphy_map *ptr_comphy_map;
+ void __iomem *comphy_base_addr, *hpipe_base_addr;
+ u32 comphy_max_count, lane, id, ret = 0;
+ u32 pcie_width = 0;
+ u32 mode;
+
+ debug_enter();
+
+ comphy_max_count = ptr_chip_cfg->comphy_lanes_count;
+ comphy_base_addr = ptr_chip_cfg->comphy_base_addr;
+ hpipe_base_addr = ptr_chip_cfg->hpipe3_base_addr;
+
+ /* Check if the first 4 lanes configured as By-4 */
+ for (lane = 0, ptr_comphy_map = serdes_map; lane < 4;
+ lane++, ptr_comphy_map++) {
+ if (ptr_comphy_map->type != COMPHY_TYPE_PEX0)
+ break;
+ pcie_width++;
+ }
+
+ for (lane = 0, ptr_comphy_map = serdes_map; lane < comphy_max_count;
+ lane++, ptr_comphy_map++) {
+ debug("Initialize serdes number %d\n", lane);
+ debug("Serdes type = 0x%x\n", ptr_comphy_map->type);
+ if (lane == 4) {
+ /*
+ * PCIe lanes above the first 4 lanes, can be only
+ * by1
+ */
+ pcie_width = 1;
+ }
+ switch (ptr_comphy_map->type) {
+ case COMPHY_TYPE_UNCONNECTED:
+ mode = COMPHY_TYPE_UNCONNECTED | COMPHY_CALLER_UBOOT;
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_OFF,
+ ptr_chip_cfg->comphy_base_addr,
+ lane, mode);
+ case COMPHY_TYPE_IGNORE:
+ continue;
+ break;
+ case COMPHY_TYPE_PEX0:
+ case COMPHY_TYPE_PEX1:
+ case COMPHY_TYPE_PEX2:
+ case COMPHY_TYPE_PEX3:
+ mode = COMPHY_FW_PCIE_FORMAT(pcie_width,
+ ptr_comphy_map->clk_src,
+ COMPHY_PCIE_MODE,
+ ptr_comphy_map->speed);
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+ ptr_chip_cfg->comphy_base_addr, lane,
+ mode);
+ break;
+ case COMPHY_TYPE_SATA0:
+ case COMPHY_TYPE_SATA1:
+ mode = COMPHY_FW_MODE_FORMAT(COMPHY_SATA_MODE);
+ ret = comphy_sata_power_up(lane, hpipe_base_addr,
+ comphy_base_addr,
+ ptr_chip_cfg->cp_index,
+ mode);
+ break;
+ case COMPHY_TYPE_USB3_HOST0:
+ case COMPHY_TYPE_USB3_HOST1:
+ mode = COMPHY_FW_MODE_FORMAT(COMPHY_USB3H_MODE);
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+ ptr_chip_cfg->comphy_base_addr, lane,
+ mode);
+ break;
+ case COMPHY_TYPE_USB3_DEVICE:
+ mode = COMPHY_FW_MODE_FORMAT(COMPHY_USB3D_MODE);
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+ ptr_chip_cfg->comphy_base_addr, lane,
+ mode);
+ break;
+ case COMPHY_TYPE_SGMII0:
+ case COMPHY_TYPE_SGMII1:
+ case COMPHY_TYPE_SGMII2:
+ /* Calculate SGMII ID */
+ id = ptr_comphy_map->type - COMPHY_TYPE_SGMII0;
+
+ if (ptr_comphy_map->speed == COMPHY_SPEED_INVALID) {
+ debug("Warning: SGMII PHY speed in lane %d is invalid, set PHY speed to 1.25G\n",
+ lane);
+ ptr_comphy_map->speed = COMPHY_SPEED_1_25G;
+ }
+
+ mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, id,
+ ptr_comphy_map->speed);
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+ ptr_chip_cfg->comphy_base_addr, lane,
+ mode);
+ break;
+ case COMPHY_TYPE_SFI0:
+ case COMPHY_TYPE_SFI1:
+ /* Calculate SFI id */
+ id = ptr_comphy_map->type - COMPHY_TYPE_SFI0;
+ mode = COMPHY_FW_FORMAT(COMPHY_SFI_MODE, id,
+ ptr_comphy_map->speed);
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+ ptr_chip_cfg->comphy_base_addr, lane, mode);
+ break;
+ case COMPHY_TYPE_RXAUI0:
+ case COMPHY_TYPE_RXAUI1:
+ mode = COMPHY_FW_MODE_FORMAT(COMPHY_RXAUI_MODE);
+ ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+ ptr_chip_cfg->comphy_base_addr, lane,
+ mode);
+ break;
+ default:
+ debug("Unknown SerDes type, skip initialize SerDes %d\n",
+ lane);
+ break;
+ }
+ if (ret == 0) {
+ /*
+ * If interface wans't initialized, set the lane to
+ * COMPHY_TYPE_UNCONNECTED state.
+ */
+ ptr_comphy_map->type = COMPHY_TYPE_UNCONNECTED;
+ pr_err("PLL is not locked - Failed to initialize lane %d\n",
+ lane);
+ }
+ }
+
+ debug_exit();
+ return 0;
+}
diff --git a/roms/u-boot/drivers/phy/marvell/comphy_mux.c b/roms/u-boot/drivers/phy/marvell/comphy_mux.c
new file mode 100644
index 000000000..10981d25e
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/comphy_mux.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ */
+
+#include <common.h>
+#include <log.h>
+#include <asm/io.h>
+
+#include "comphy_core.h"
+
+/*
+ * comphy_mux_check_config()
+ * description: this function passes over the COMPHY lanes and check if the type
+ * is valid for specific lane. If the type is not valid,
+ * the function update the struct and set the type of the lane as
+ * COMPHY_TYPE_UNCONNECTED
+ */
+static void comphy_mux_check_config(struct comphy_mux_data *mux_data,
+ struct comphy_map *comphy_map_data, int comphy_max_lanes)
+{
+ struct comphy_mux_options *mux_opt;
+ int lane, opt, valid;
+
+ debug_enter();
+
+ for (lane = 0; lane < comphy_max_lanes;
+ lane++, comphy_map_data++, mux_data++) {
+ /* Don't check ignored COMPHYs */
+ if (comphy_map_data->type == COMPHY_TYPE_IGNORE)
+ continue;
+
+ mux_opt = mux_data->mux_values;
+ for (opt = 0, valid = 0; opt < mux_data->max_lane_values;
+ opt++, mux_opt++) {
+ if (mux_opt->type == comphy_map_data->type) {
+ valid = 1;
+ break;
+ }
+ }
+ if (valid == 0) {
+ debug("lane number %d, had invalid type %d\n",
+ lane, comphy_map_data->type);
+ debug("set lane %d as type %d\n", lane,
+ COMPHY_TYPE_UNCONNECTED);
+ comphy_map_data->type = COMPHY_TYPE_UNCONNECTED;
+ } else {
+ debug("lane number %d, has type %d\n",
+ lane, comphy_map_data->type);
+ }
+ }
+
+ debug_exit();
+}
+
+static u32 comphy_mux_get_mux_value(struct comphy_mux_data *mux_data,
+ u32 type, int lane)
+{
+ struct comphy_mux_options *mux_opt;
+ int opt;
+ u32 value = 0;
+
+ debug_enter();
+
+ mux_opt = mux_data->mux_values;
+ for (opt = 0 ; opt < mux_data->max_lane_values; opt++, mux_opt++) {
+ if (mux_opt->type == type) {
+ value = mux_opt->mux_value;
+ break;
+ }
+ }
+
+ debug_exit();
+
+ return value;
+}
+
+static void comphy_mux_reg_write(struct comphy_mux_data *mux_data,
+ struct comphy_map *comphy_map_data,
+ int comphy_max_lanes,
+ void __iomem *selector_base,
+ const fdt32_t *mux_lane_order, u32 bitcount)
+{
+ u32 lane, value, offset, mask;
+
+ debug_enter();
+
+ for (lane = 0; lane < comphy_max_lanes;
+ lane++, comphy_map_data++, mux_data++) {
+ if (comphy_map_data->type == COMPHY_TYPE_IGNORE)
+ continue;
+
+ /*
+ * if the order of nodes in selector base register is
+ * nontrivial, use mapping from mux_lane_order
+ */
+ if (mux_lane_order)
+ offset = fdt32_to_cpu(mux_lane_order[lane]) * bitcount;
+ else
+ offset = lane * bitcount;
+
+ mask = (((1 << bitcount) - 1) << offset);
+ value = (comphy_mux_get_mux_value(mux_data,
+ comphy_map_data->type,
+ lane) << offset);
+ reg_set(selector_base, value, mask);
+ }
+
+ debug_exit();
+}
+
+void comphy_mux_init(struct chip_serdes_phy_config *chip_cfg,
+ struct comphy_map *comphy_map_data,
+ void __iomem *selector_base)
+{
+ struct comphy_mux_data *mux_data;
+ const fdt32_t *mux_lane_order;
+ u32 mux_bitcount;
+ u32 comphy_max_lanes;
+
+ debug_enter();
+
+ comphy_max_lanes = chip_cfg->comphy_lanes_count;
+ mux_data = chip_cfg->mux_data;
+ mux_lane_order = chip_cfg->comphy_mux_lane_order;
+ mux_bitcount = chip_cfg->comphy_mux_bitcount;
+
+ /* check if the configuration is valid */
+ comphy_mux_check_config(mux_data, comphy_map_data, comphy_max_lanes);
+ /* Init COMPHY selectors */
+ comphy_mux_reg_write(mux_data, comphy_map_data, comphy_max_lanes,
+ selector_base, mux_lane_order, mux_bitcount);
+
+ debug_exit();
+}
diff --git a/roms/u-boot/drivers/phy/marvell/sata.h b/roms/u-boot/drivers/phy/marvell/sata.h
new file mode 100644
index 000000000..41db7aa8b
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/sata.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ */
+
+#ifndef _SATA_H_
+#define _SATA_H_
+
+/* SATA3 Unit address */
+#define SATA3_VENDOR_ADDRESS 0xA0
+#define SATA3_VENDOR_ADDR_OFSSET 0
+#define SATA3_VENDOR_ADDR_MASK (0xFFFFFFFF << SATA3_VENDOR_ADDR_OFSSET)
+#define SATA3_VENDOR_DATA 0xA4
+
+#define SATA_CONTROL_REG 0x0
+#define SATA3_CTRL_SATA0_PD_OFFSET 6
+#define SATA3_CTRL_SATA0_PD_MASK (1 << SATA3_CTRL_SATA0_PD_OFFSET)
+#define SATA3_CTRL_SATA1_PD_OFFSET 14
+#define SATA3_CTRL_SATA1_PD_MASK (1 << SATA3_CTRL_SATA1_PD_OFFSET)
+#define SATA3_CTRL_SATA1_ENABLE_OFFSET 22
+#define SATA3_CTRL_SATA1_ENABLE_MASK (1 << SATA3_CTRL_SATA1_ENABLE_OFFSET)
+#define SATA3_CTRL_SATA_SSU_OFFSET 23
+#define SATA3_CTRL_SATA_SSU_MASK (1 << SATA3_CTRL_SATA_SSU_OFFSET)
+
+#define SATA_MBUS_SIZE_SELECT_REG 0x4
+#define SATA_MBUS_REGRET_EN_OFFSET 7
+#define SATA_MBUS_REGRET_EN_MASK (0x1 << SATA_MBUS_REGRET_EN_OFFSET)
+
+#endif /* _SATA_H_ */
diff --git a/roms/u-boot/drivers/phy/marvell/utmi_phy.h b/roms/u-boot/drivers/phy/marvell/utmi_phy.h
new file mode 100644
index 000000000..8a570bae7
--- /dev/null
+++ b/roms/u-boot/drivers/phy/marvell/utmi_phy.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ */
+
+#ifndef _UTMI_PHY_H_
+#define _UTMI_PHY_H_
+
+#define UTMI_USB_CFG_DEVICE_EN_OFFSET 0
+#define UTMI_USB_CFG_DEVICE_EN_MASK \
+ (0x1 << UTMI_USB_CFG_DEVICE_EN_OFFSET)
+#define UTMI_USB_CFG_DEVICE_MUX_OFFSET 1
+#define UTMI_USB_CFG_DEVICE_MUX_MASK \
+ (0x1 << UTMI_USB_CFG_DEVICE_MUX_OFFSET)
+#define UTMI_USB_CFG_PLL_OFFSET 25
+#define UTMI_USB_CFG_PLL_MASK \
+ (0x1 << UTMI_USB_CFG_PLL_OFFSET)
+
+#define UTMI_PHY_CFG_PU_OFFSET 5
+#define UTMI_PHY_CFG_PU_MASK \
+ (0x1 << UTMI_PHY_CFG_PU_OFFSET)
+
+#define UTMI_PLL_CTRL_REG 0x0
+#define UTMI_PLL_CTRL_REFDIV_OFFSET 0
+#define UTMI_PLL_CTRL_REFDIV_MASK \
+ (0x7f << UTMI_PLL_CTRL_REFDIV_OFFSET)
+#define UTMI_PLL_CTRL_FBDIV_OFFSET 16
+#define UTMI_PLL_CTRL_FBDIV_MASK \
+ (0x1FF << UTMI_PLL_CTRL_FBDIV_OFFSET)
+#define UTMI_PLL_CTRL_SEL_LPFR_OFFSET 28
+#define UTMI_PLL_CTRL_SEL_LPFR_MASK \
+ (0x3 << UTMI_PLL_CTRL_SEL_LPFR_OFFSET)
+#define UTMI_PLL_CTRL_PLL_RDY_OFFSET 31
+#define UTMI_PLL_CTRL_PLL_RDY_MASK \
+ (0x1 << UTMI_PLL_CTRL_PLL_RDY_OFFSET)
+
+#define UTMI_CALIB_CTRL_REG 0x8
+#define UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET 8
+#define UTMI_CALIB_CTRL_IMPCAL_VTH_MASK \
+ (0x7 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET)
+#define UTMI_CALIB_CTRL_IMPCAL_START_OFFSET 13
+#define UTMI_CALIB_CTRL_IMPCAL_START_MASK \
+ (0x1 << UTMI_CALIB_CTRL_IMPCAL_START_OFFSET)
+#define UTMI_CALIB_CTRL_PLLCAL_START_OFFSET 22
+#define UTMI_CALIB_CTRL_PLLCAL_START_MASK \
+ (0x1 << UTMI_CALIB_CTRL_PLLCAL_START_OFFSET)
+#define UTMI_CALIB_CTRL_IMPCAL_DONE_OFFSET 23
+#define UTMI_CALIB_CTRL_IMPCAL_DONE_MASK \
+ (0x1 << UTMI_CALIB_CTRL_IMPCAL_DONE_OFFSET)
+#define UTMI_CALIB_CTRL_PLLCAL_DONE_OFFSET 31
+#define UTMI_CALIB_CTRL_PLLCAL_DONE_MASK \
+ (0x1 << UTMI_CALIB_CTRL_PLLCAL_DONE_OFFSET)
+
+#define UTMI_TX_CH_CTRL_REG 0x0
+#define UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET 12
+#define UTMI_TX_CH_CTRL_DRV_EN_LS_MASK \
+ (0xf << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET)
+#define UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET 16
+#define UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK \
+ (0xf << UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET)
+#define UTMI_TX_CH_CTRL_AMP_OFFSET 20
+#define UTMI_TX_CH_CTRL_AMP_MASK \
+ (0x7 << UTMI_TX_CH_CTRL_AMP_OFFSET)
+
+#define UTMI_RX_CH_CTRL0_REG 0x8
+#define UTMI_RX_CH_CTRL0_DISCON_THRESH_OFFSET 8
+#define UTMI_RX_CH_CTRL0_DISCON_THRESH_MASK \
+ (0x3 << UTMI_RX_CH_CTRL0_DISCON_THRESH_OFFSET)
+#define UTMI_RX_CH_CTRL0_SQ_DET_OFFSET 15
+#define UTMI_RX_CH_CTRL0_SQ_DET_MASK \
+ (0x1 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET)
+#define UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET 28
+#define UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK \
+ (0x1 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET)
+
+#define UTMI_RX_CH_CTRL1_REG 0xc
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET 0
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK \
+ (0x7 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET)
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET 3
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_MASK \
+ (0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET)
+
+#define UTMI_CTRL_STATUS0_REG 0x18
+#define UTMI_CTRL_STATUS0_SUSPENDM_OFFSET 22
+#define UTMI_CTRL_STATUS0_SUSPENDM_MASK \
+ (0x1 << UTMI_CTRL_STATUS0_SUSPENDM_OFFSET)
+#define UTMI_CTRL_STATUS0_TEST_SEL_OFFSET 25
+#define UTMI_CTRL_STATUS0_TEST_SEL_MASK \
+ (0x1 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET)
+
+#define UTMI_CHGDTC_CTRL_REG 0x2c
+#define UTMI_CHGDTC_CTRL_VDAT_OFFSET 8
+#define UTMI_CHGDTC_CTRL_VDAT_MASK \
+ (0x3 << UTMI_CHGDTC_CTRL_VDAT_OFFSET)
+#define UTMI_CHGDTC_CTRL_VSRC_OFFSET 10
+#define UTMI_CHGDTC_CTRL_VSRC_MASK \
+ (0x3 << UTMI_CHGDTC_CTRL_VSRC_OFFSET)
+
+#endif /* _UTMI_PHY_H_ */
+