[U-Boot] [PATCH 1/9] drivers/phy: Add Marvell SerDes / PHY drivers used on Armada 7K/8K

This version is based on the Marvell U-Boot version with this patch applied as latest patch:
Git ID 7f408573: "fix: comphy: cp110: add comphy initialization for usb device mode" from 2016-07-05.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- drivers/phy/marvell/Makefile | 1 + drivers/phy/marvell/comphy.h | 18 +- drivers/phy/marvell/comphy_core.c | 3 + drivers/phy/marvell/comphy_cp110.c | 1726 ++++++++++++++++++++++++++++++++++++ drivers/phy/marvell/comphy_hpipe.h | 38 + drivers/phy/marvell/sata.h | 30 + drivers/phy/marvell/utmi_phy.h | 90 ++ 7 files changed, 1904 insertions(+), 2 deletions(-) create mode 100644 drivers/phy/marvell/comphy_cp110.c create mode 100644 drivers/phy/marvell/sata.h create mode 100644 drivers/phy/marvell/utmi_phy.h
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile index 91df554..f181505 100644 --- a/drivers/phy/marvell/Makefile +++ b/drivers/phy/marvell/Makefile @@ -5,3 +5,4 @@ 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/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy.h index 5c50e9c..df5b7d5 100644 --- a/drivers/phy/marvell/comphy.h +++ b/drivers/phy/marvell/comphy.h @@ -60,6 +60,9 @@ #define COMMON_PHY_SD_CTRL1_RXAUI0_MASK \ (0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET)
+/* ToDo: Get this address via DT */ +#define MVEBU_CP0_REGS_BASE 0xF2000000UL + #define DFX_DEV_GEN_CTRL12 (MVEBU_CP0_REGS_BASE + 0x400280) #define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET 7 #define DFX_DEV_GEN_PCIE_CLK_SRC_MASK \ @@ -117,10 +120,21 @@ static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg, return -1; } #endif -int comphy_ap806_init(struct chip_serdes_phy_config *ptr_chip_cfg, - struct comphy_map *serdes_map); + +#ifdef CONFIG_ARMADA_8K int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, struct comphy_map *serdes_map); +#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; +} +#endif
void comphy_dedicated_phys_init(void);
diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index 519bc16..799e034 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -139,6 +139,9 @@ static int comphy_probe(struct udevice *dev) if (of_device_is_compatible(dev, "marvell,comphy-armada-3700")) chip_cfg->ptr_comphy_chip_init = comphy_a3700_init;
+ if (of_device_is_compatible(dev, "marvell,comphy-cp110")) + chip_cfg->ptr_comphy_chip_init = comphy_cp110_init; + /* * Bail out if no chip_init function is defined, e.g. no * compatible node is found diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c new file mode 100644 index 0000000..25c067d --- /dev/null +++ b/drivers/phy/marvell/comphy_cp110.c @@ -0,0 +1,1726 @@ +/* + * Copyright (C) 2015-2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> + +#include "comphy.h" +#include "comphy_hpipe.h" +#include "sata.h" +#include "utmi_phy.h" + +DECLARE_GLOBAL_DATA_PTR; + +#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) + +struct utmi_phy_data { + void __iomem *utmi_base_addr; + void __iomem *usb_cfg_addr; + void __iomem *utmi_cfg_addr; + u32 utmi_phy_port; +}; + +/* + * For CP-110 we have 2 Selector registers "PHY Selectors", + * and "PIPE Selectors". + * PIPE selector include USB and PCIe options. + * PHY selector include the Ethernet and SATA options, every Ethernet + * option has different options, for example: serdes lane2 had option + * Eth_port_0 that include (SGMII0, XAUI0, RXAUI0, KR) + */ +struct comphy_mux_data cp110_comphy_phy_mux_data[] = { + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII2, 0x1}, /* Lane 0 */ + {PHY_TYPE_XAUI2, 0x1}, {PHY_TYPE_SATA1, 0x4} } }, + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII3, 0x1}, /* Lane 1 */ + {PHY_TYPE_XAUI3, 0x1}, {PHY_TYPE_SATA0, 0x4} } }, + {6, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x1}, /* Lane 2 */ + {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1}, + {PHY_TYPE_KR, 0x1}, {PHY_TYPE_SATA0, 0x4} } }, + {8, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x1}, /* Lane 3 */ + {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1}, + {PHY_TYPE_KR, 0x1}, {PHY_TYPE_XAUI1, 0x1}, + {PHY_TYPE_RXAUI1, 0x1}, {PHY_TYPE_SATA1, 0x4} } }, + {7, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x2}, /* Lane 4 */ + {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1}, {PHY_TYPE_KR, 0x1}, + {PHY_TYPE_SGMII2, 0x1}, {PHY_TYPE_XAUI2, 0x1} } }, + {6, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_XAUI1, 0x1}, /* Lane 5 */ + {PHY_TYPE_RXAUI1, 0x1}, {PHY_TYPE_SGMII3, 0x1}, + {PHY_TYPE_XAUI3, 0x1}, {PHY_TYPE_SATA1, 0x4} } }, +}; + +struct comphy_mux_data cp110_comphy_pipe_mux_data[] = { + {2, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_PEX0, 0x4} } }, /* Lane 0 */ + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 1 */ + {PHY_TYPE_USB3_HOST0, 0x1}, {PHY_TYPE_USB3_DEVICE, 0x2}, + {PHY_TYPE_PEX0, 0x4} } }, + {3, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 2 */ + {PHY_TYPE_USB3_HOST0, 0x1}, {PHY_TYPE_PEX0, 0x4} } }, + {3, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 3 */ + {PHY_TYPE_USB3_HOST1, 0x1}, {PHY_TYPE_PEX0, 0x4} } }, + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 4 */ + {PHY_TYPE_USB3_HOST1, 0x1}, + {PHY_TYPE_USB3_DEVICE, 0x2}, {PHY_TYPE_PEX1, 0x4} } }, + {2, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_PEX2, 0x4} } }, /* Lane 5 */ +}; + +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_pcie_power_up(u32 lane, u32 pcie_width, + bool clk_src, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + u32 pcie_clk = 0; /* set input by default */ + + debug_enter(); + + /* + * ToDo: + * Add SAR (Sample-At-Reset) configuration for the PCIe clock + * direction. SAR code is currently not ported from Marvell + * U-Boot to mainline version. + * + * SerDes Lane 4/5 got the PCIe ref-clock #1, + * and SerDes Lane 0 got PCIe ref-clock #0 + */ + debug("PCIe clock = %x\n", pcie_clk); + debug("PCIe width = %d\n", pcie_width); + + /* enable PCIe by4 and by2 */ + if (lane == 0) { + if (pcie_width == 4) { + reg_set(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 (pcie_width == 2) { + reg_set(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, + * we need to configure the clock-source MUX. + * By default, the clock source is from lane 4 + */ + if (pcie_clk && clk_src && (lane == 5)) { + reg_set((void __iomem *)DFX_DEV_GEN_CTRL12, + 0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET, + DFX_DEV_GEN_PCIE_CLK_SRC_MASK); + } + + debug("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 */ + debug("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 (pcie_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 (pcie_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 == (pcie_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 (pcie_clk) { + 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 (pcie_clk) { /* 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 (pcie_clk) { /* 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 (pcie_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 (pcie_clk) { + 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); + + debug("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); + + /* 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); + + debug("stage: Comphy power up\n"); + + /* + * For PCIe by4 or by2 - release from reset only after finish to + * configure all lanes + */ + if ((pcie_width == 1) || (lane == (pcie_width - 1))) { + u32 i, start_lane, end_lane; + + if (pcie_width != 1) { + /* allows writing to all lanes in one write */ + reg_set(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 = pcie_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(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 (pcie_width != 1) { + /* disable writing to all lanes with one write */ + reg_set(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); + } + + debug("stage: Check PLL\n"); + /* Read lane status */ + for (i = start_lane; i < end_lane; i++) { + addr = HPIPE_ADDR(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) { + debug("Read from reg = %p - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, + data); + error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); + ret = 0; + } + } + } + + debug_exit(); + return ret; +} + +static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("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 |= 0x1 << 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 */ + debug("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 |= 0x0 << 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 */ + reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, + 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET, + HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK); + /* Set reference clock to come from group 1 - 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Set reference frequcency select - 0x2 */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* Set PHY mode to USB - 0x5 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x5 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set the amount of time spent in the LoZ state - set for 0x7 */ + reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, + 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, + HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); + /* Set max PHY generation setting - 5Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x1 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 20Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, + HPIPE_LOOPBACK_SEL_MASK); + /* select de-emphasize 3.5db */ + reg_set(hpipe_addr + HPIPE_LANE_CONFIG0_REG, + 0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET, + HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK); + /* override tx margining from the MAC */ + reg_set(hpipe_addr + HPIPE_TST_MODE_CTRL_REG, + 0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET, + HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK); + + /* Start analog paramters from ETP(HW) */ + debug("stage: Analog paramters from ETP(HW)\n"); + /* Set Pin DFE_PAT_DIS -> Bit[1]: PIN_DFE_PAT_DIS = 0x0 */ + mask = HPIPE_LANE_CFG4_DFE_CTRL_MASK; + data = 0x1 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET; + /* Set Override PHY DFE control pins for 0x1 */ + mask |= HPIPE_LANE_CFG4_DFE_OVER_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET; + /* Set Spread Spectrum Clock Enable fot 0x1 */ + mask |= HPIPE_LANE_CFG4_SSC_CTRL_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); + /* End of analog parameters */ + + debug("stage: Comphy power up\n"); + /* Release from PIPE soft reset */ + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, + 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, + HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); + + /* wait 15ms - for comphy calibration done */ + debug("stage: Check PLL\n"); + /* Read lane status */ + addr = hpipe_addr + HPIPE_LANE_STATUS1_REG; + data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, data); + error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); + ret = 0; + } + + debug_exit(); + return ret; +} + +static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base, int comphy_index) +{ + u32 mask, data, i, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + 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 < (comphy_index + 1); i++) + sata_node = fdt_node_offset_by_compatible( + gd->fdt_blob, sata_node, "marvell,armada-8k-ahci"); + + if (sata_node == 0) { + error("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) { + error("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); + + debug("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 |= 0x0 << 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; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Set select data width 40Bit - SATA mode only */ + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, + 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET, + COMMON_PHY_CFG6_IF_40_SEL_MASK); + + /* release from hard reset in SD external */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + debug("stage: Comphy configuration\n"); + /* Start comphy Configuration */ + /* Set reference clock to comes from group 1 - choose 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Reference frequency select set 1 (for SATA = 25Mhz) */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* PHY mode select (set SATA = 0x0 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set max PHY generation setting - 6Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 40Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + + debug("stage: Analog paramters from ETP(HW)\n"); + /* + * TODO: Set analog paramters from ETP(HW) - for now use the + * default datas + */ + + /* DFE reset sequence */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + /* SW reset for interupt logic */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + + debug("stage: Comphy power up\n"); + /* + * 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); + + debug("stage: Check PLL\n"); + + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_TX_MASK & + SD_EXTERNAL_STATUS0_PLL_RX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)); + ret = 0; + } + + debug_exit(); + return ret; +} + +static int comphy_sgmii_power_up(u32 lane, u32 sgmii_speed, + void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("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 |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + if (sgmii_speed == PHY_SPEED_1_25G) { + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } else { + /* 3.125G */ + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_REFCLK_SEL_MASK; + data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + 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); + + /* Set analog paramters from ETP(HW) - for now use the default datas */ + debug("stage: Analog paramters from ETP(HW)\n"); + + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = 0; + } + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = 0; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + return ret; +} + +static int comphy_kr_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("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 |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_ICP_FORCE_MASK; + data = 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET; + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Set analog paramters from ETP(HW) */ + debug("stage: Analog paramters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); + /* 0x7-DFE Resolution control */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + /* 0xd-G1_Setting_0 */ + mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; + data = 0x1c << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data |= 0xe << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); + /* Genration 1 setting 2 (G1_Setting_2) */ + mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; + data = 0x0 << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; + mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); + /* Transmitter Slew Rate Control register (tx_reg1) */ + mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK; + data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET; + mask |= HPIPE_TX_REG1_SLC_EN_MASK; + data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask); + /* Impedance Calibration Control register (cal_reg1) */ + mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK; + data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK; + data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask); + /* Generation 1 Setting 5 (g1_setting_5) */ + mask = HPIPE_G1_SETTING_5_G1_ICP_MASK; + data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask); + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + /* Genration 1 setting 3 (G1_Setting_3) */ + mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = 0; + } + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = 0; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + return ret; +} + +static int comphy_rxauii_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("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 |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + if (lane == 2) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI0_MASK); + } + if (lane == 4) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI1_MASK); + } + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, + 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET, + HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK); + + /* Set analog paramters from ETP(HW) */ + debug("stage: Analog paramters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, + 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET, + SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK); + /* 0x7-DFE Resolution control */ + reg_set(hpipe_addr + HPIPE_DFE_REG0, 0x1 << HPIPE_DFE_RES_FORCE_OFFSET, + HPIPE_DFE_RES_FORCE_MASK); + /* 0xd-G1_Setting_0 */ + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0xd << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = 0; + } + + /* RX init */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, + 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET, + SD_EXTERNAL_CONFIG1_RX_INIT_MASK); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = 0; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + 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_USB_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_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_base_addr + UTMI_PLL_CTRL_REG, data, mask); + + /* Impedance Calibration Threshold Setting */ + reg_set(utmi_base_addr + UTMI_CALIB_CTRL_REG, + 0x6 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET, + UTMI_CALIB_CTRL_IMPCAL_VTH_MASK); + + /* Set LS TX driver strength coarse control */ + mask = UTMI_TX_CH_CTRL_DRV_EN_LS_MASK; + data = 0x3 << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET; + /* Set LS TX driver fine adjustment */ + mask |= UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK; + data |= 0x3 << UTMI_TX_CH_CTRL_IMP_SEL_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 = 0x0 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET; + /* Enable analog squelch detect */ + mask |= UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK; + data |= 0x1 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_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_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_base_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) { + error("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) { + error("PLL calibration is not done\n"); + debug("Read from reg = %p - value = 0x%x\n", addr, data); + ret = 0; + } + + addr = utmi_base_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) { + error("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. Powe 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_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_base_addr, + cp110_utmi_data[i].usb_cfg_addr, + cp110_utmi_data[i].utmi_cfg_addr, + cp110_utmi_data[i].utmi_phy_port)) { + error("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_USB_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; + int i; + + debug_enter(); + debug("Initialize USB UTMI PHYs\n"); + + /* Find the UTMI phy node in device tree and go over them */ + node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, + "marvell,mvebu-utmi-2.6.0"); + + i = 0; + while (node > 0) { + /* get base address of UTMI phy */ + cp110_utmi_data[i].utmi_base_addr = + (void __iomem *)fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, node, "reg", 0, NULL, true); + if (cp110_utmi_data[i].utmi_base_addr == NULL) { + error("UTMI PHY base address is invalid\n"); + i++; + continue; + } + + /* get usb config address */ + cp110_utmi_data[i].usb_cfg_addr = + (void __iomem *)fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, node, "reg", 1, NULL, true); + if (cp110_utmi_data[i].usb_cfg_addr == NULL) { + error("UTMI PHY base address is invalid\n"); + i++; + continue; + } + + /* get UTMI config address */ + cp110_utmi_data[i].utmi_cfg_addr = + (void __iomem *)fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, node, "reg", 2, NULL, true); + if (cp110_utmi_data[i].utmi_cfg_addr == NULL) { + error("UTMI PHY base address is invalid\n"); + i++; + continue; + } + + /* + * get the port number (to check if the utmi connected to + * host/device) + */ + cp110_utmi_data[i].utmi_phy_port = fdtdec_get_int( + gd->fdt_blob, node, "utmi-port", UTMI_PHY_INVALID); + if (cp110_utmi_data[i].utmi_phy_port == UTMI_PHY_INVALID) { + error("UTMI PHY port type is invalid\n"); + i++; + continue; + } + + node = fdt_node_offset_by_compatible( + gd->fdt_blob, node, "marvell,mvebu-utmi-2.6.0"); + i++; + } + + if (i > 0) + comphy_utmi_phy_init(i, cp110_utmi_data); + + debug_exit(); +} + +static void comphy_mux_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, + struct comphy_map *serdes_map) +{ + void __iomem *comphy_base_addr; + struct comphy_map comphy_map_pipe_data[MAX_LANE_OPTIONS]; + struct comphy_map comphy_map_phy_data[MAX_LANE_OPTIONS]; + u32 lane, comphy_max_count; + + comphy_max_count = ptr_chip_cfg->comphy_lanes_count; + comphy_base_addr = ptr_chip_cfg->comphy_base_addr; + + /* + * Copy the SerDes map configuration for PIPE map and PHY map + * the comphy_mux_init modify the type of the lane if the type + * is not valid because we have 2 selectores run the + * comphy_mux_init twice and after that update the original + * serdes_map + */ + for (lane = 0; lane < comphy_max_count; lane++) { + comphy_map_pipe_data[lane].type = serdes_map[lane].type; + comphy_map_pipe_data[lane].speed = serdes_map[lane].speed; + comphy_map_phy_data[lane].type = serdes_map[lane].type; + comphy_map_phy_data[lane].speed = serdes_map[lane].speed; + } + ptr_chip_cfg->mux_data = cp110_comphy_phy_mux_data; + comphy_mux_init(ptr_chip_cfg, comphy_map_phy_data, + comphy_base_addr + COMMON_SELECTOR_PHY_OFFSET); + + ptr_chip_cfg->mux_data = cp110_comphy_pipe_mux_data; + comphy_mux_init(ptr_chip_cfg, comphy_map_pipe_data, + comphy_base_addr + COMMON_SELECTOR_PIPE_OFFSET); + /* Fix the type after check the PHY and PIPE configuration */ + for (lane = 0; lane < comphy_max_count; lane++) { + if ((comphy_map_pipe_data[lane].type == PHY_TYPE_UNCONNECTED) && + (comphy_map_phy_data[lane].type == PHY_TYPE_UNCONNECTED)) + serdes_map[lane].type = PHY_TYPE_UNCONNECTED; + } +} + +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, ret = 0; + u32 pcie_width = 0; + + 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; + + /* Config Comphy mux configuration */ + comphy_mux_cp110_init(ptr_chip_cfg, serdes_map); + + /* 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 != PHY_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 PHY_TYPE_UNCONNECTED: + continue; + break; + case PHY_TYPE_PEX0: + case PHY_TYPE_PEX1: + case PHY_TYPE_PEX2: + case PHY_TYPE_PEX3: + ret = comphy_pcie_power_up( + lane, pcie_width, ptr_comphy_map->clk_src, + hpipe_base_addr, comphy_base_addr); + break; + case PHY_TYPE_SATA0: + case PHY_TYPE_SATA1: + case PHY_TYPE_SATA2: + case PHY_TYPE_SATA3: + ret = comphy_sata_power_up( + lane, hpipe_base_addr, comphy_base_addr, + ptr_chip_cfg->comphy_index); + break; + case PHY_TYPE_USB3_HOST0: + case PHY_TYPE_USB3_HOST1: + case PHY_TYPE_USB3_DEVICE: + ret = comphy_usb3_power_up(lane, hpipe_base_addr, + comphy_base_addr); + break; + case PHY_TYPE_SGMII0: + case PHY_TYPE_SGMII1: + case PHY_TYPE_SGMII2: + case PHY_TYPE_SGMII3: + if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { + debug("Warning: SGMII PHY speed in lane %d is invalid, set PHY speed to 1.25G\n", + lane); + ptr_comphy_map->speed = PHY_SPEED_1_25G; + } + ret = comphy_sgmii_power_up( + lane, ptr_comphy_map->speed, hpipe_base_addr, + comphy_base_addr); + break; + case PHY_TYPE_KR: + ret = comphy_kr_power_up(lane, hpipe_base_addr, + comphy_base_addr); + break; + case PHY_TYPE_RXAUI0: + case PHY_TYPE_RXAUI1: + ret = comphy_rxauii_power_up(lane, hpipe_base_addr, + comphy_base_addr); + break; + default: + debug("Unknown SerDes type, skip initialize SerDes %d\n", + lane); + break; + } + if (ret == 0) { + /* + * If interface wans't initialiuzed, set the lane to + * PHY_TYPE_UNCONNECTED state. + */ + ptr_comphy_map->type = PHY_TYPE_UNCONNECTED; + error("PLL is not locked - Failed to initialize lane %d\n", + lane); + } + } + + debug_exit(); + return 0; +} diff --git a/drivers/phy/marvell/comphy_hpipe.h b/drivers/phy/marvell/comphy_hpipe.h index 0c9b500..179e910 100644 --- a/drivers/phy/marvell/comphy_hpipe.h +++ b/drivers/phy/marvell/comphy_hpipe.h @@ -78,6 +78,14 @@ #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 @@ -94,6 +102,9 @@ (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) @@ -145,6 +156,14 @@ #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 @@ -164,6 +183,9 @@ #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) @@ -197,6 +219,14 @@ #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 \ @@ -262,6 +292,9 @@ (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 @@ -289,6 +322,11 @@ #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 \ diff --git a/drivers/phy/marvell/sata.h b/drivers/phy/marvell/sata.h new file mode 100644 index 0000000..be2ba54 --- /dev/null +++ b/drivers/phy/marvell/sata.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015-2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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/drivers/phy/marvell/utmi_phy.h b/drivers/phy/marvell/utmi_phy.h new file mode 100644 index 0000000..01e53ba --- /dev/null +++ b/drivers/phy/marvell/utmi_phy.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2015-2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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_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 0xC +#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_RX_CH_CTRL0_REG 0x14 +#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 0x18 +#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET 0 +#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK \ + (0x3 << 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 0x24 +#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 0x38 +#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_ */ +

To enable this driver on Armada 7K/8K this patch adds the compatibility property to the list.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- drivers/usb/host/xhci-mvebu.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c index e09e87a..23c241a 100644 --- a/drivers/usb/host/xhci-mvebu.c +++ b/drivers/usb/host/xhci-mvebu.c @@ -79,6 +79,7 @@ static int xhci_usb_ofdata_to_platdata(struct udevice *dev)
static const struct udevice_id xhci_usb_ids[] = { { .compatible = "marvell,armada3700-xhci" }, + { .compatible = "marvell,armada-8k-xhci" }, { } };

To allow a board- / platform-specific ahci_port_base() function, this patch removes "static inline" and adds __weak to this function. This will be used by the upcoming Armada 7K/8K SATA / AHCI support, which unfortunately needs a different port base address calculation.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- drivers/block/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index e3e783a..cd99737 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -45,7 +45,7 @@ u16 *ataid[AHCI_MAX_PORTS]; #define WAIT_MS_FLUSH 5000 #define WAIT_MS_LINKUP 200
-static inline void __iomem *ahci_port_base(void __iomem *base, u32 port) +__weak void __iomem *ahci_port_base(void __iomem *base, u32 port) { return base + 0x100 + (port * 0x80); }

This patch integrates the Armada 7K/8K dts files from the latest submission on the linux-arm-kernel mailing list.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- arch/arm/dts/Makefile | 1 + arch/arm/dts/armada-7040-db.dts | 148 ++++++++++++++++++++++ arch/arm/dts/armada-7040.dtsi | 55 ++++++++ arch/arm/dts/armada-ap806-quad.dtsi | 82 ++++++++++++ arch/arm/dts/armada-ap806.dtsi | 229 ++++++++++++++++++++++++++++++++++ arch/arm/dts/armada-cp110-master.dtsi | 228 +++++++++++++++++++++++++++++++++ 6 files changed, 743 insertions(+) create mode 100644 arch/arm/dts/armada-7040-db.dts create mode 100644 arch/arm/dts/armada-7040.dtsi create mode 100644 arch/arm/dts/armada-ap806-quad.dtsi create mode 100644 arch/arm/dts/armada-ap806.dtsi create mode 100644 arch/arm/dts/armada-cp110-master.dtsi
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 4a51de1..92155f5 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -71,6 +71,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \ armada-375-db.dtb \ armada-388-clearfog.dtb \ armada-388-gp.dtb \ + armada-7040-db.dtb \ armada-xp-gp.dtb \ armada-xp-maxbcm.dtb \ armada-xp-synology-ds414.dtb \ diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts new file mode 100644 index 0000000..070b589 --- /dev/null +++ b/arch/arm/dts/armada-7040-db.dts @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library 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 (at your option) any later version. + * + * This library 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Device Tree file for Marvell Armada 7040 Development board platform + */ + +#include "armada-7040.dtsi" + +/ { + model = "Marvell Armada 7040 DB board"; + compatible = "marvell,armada7040-db", "marvell,armada7040", + "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&spi0 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0 0x200000>; + }; + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xce0000>; + }; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + + +&cpm_pcie2 { + status = "okay"; +}; + +&cpm_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&cpm_spi1 { + status = "okay"; + + spi-flash@0 { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <20000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x200000>; + }; + + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xe00000>; + }; + }; + }; +}; + +&cpm_sata0 { + status = "okay"; +}; + +&cpm_usb3_0 { + status = "okay"; +}; + +&cpm_usb3_1 { + status = "okay"; +}; diff --git a/arch/arm/dts/armada-7040.dtsi b/arch/arm/dts/armada-7040.dtsi new file mode 100644 index 0000000..78d995d --- /dev/null +++ b/arch/arm/dts/armada-7040.dtsi @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library 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 (at your option) any later version. + * + * This library 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Device Tree file for the Armada 7040 SoC, made of an AP806 Quad and + * one CP110. + */ + +#include "armada-ap806-quad.dtsi" +#include "armada-cp110-master.dtsi" + +/ { + model = "Marvell Armada 7040"; + compatible = "marvell,armada7040", "marvell,armada-ap806-quad", + "marvell,armada-ap806"; +}; diff --git a/arch/arm/dts/armada-ap806-quad.dtsi b/arch/arm/dts/armada-ap806-quad.dtsi new file mode 100644 index 0000000..ba43a43 --- /dev/null +++ b/arch/arm/dts/armada-ap806-quad.dtsi @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library 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 (at your option) any later version. + * + * This library 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Device Tree file for Marvell Armada AP806. + */ + +#include "armada-ap806.dtsi" + +/ { + model = "Marvell Armada AP806 Quad"; + compatible = "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@000 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x000>; + enable-method = "psci"; + }; + cpu@001 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x001>; + enable-method = "psci"; + }; + cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x100>; + enable-method = "psci"; + }; + cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x101>; + enable-method = "psci"; + }; + }; +}; diff --git a/arch/arm/dts/armada-ap806.dtsi b/arch/arm/dts/armada-ap806.dtsi new file mode 100644 index 0000000..20d256b --- /dev/null +++ b/arch/arm/dts/armada-ap806.dtsi @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library 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 (at your option) any later version. + * + * This library 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Device Tree file for Marvell Armada AP806. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/dts-v1/; + +/ { + model = "Marvell Armada AP806"; + compatible = "marvell,armada-ap806"; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + ap806 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + config-space { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0x0 0x0 0xf0000000 0x1000000>; + + gic: interrupt-controller@210000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-controller; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + reg = <0x210000 0x10000>, + <0x220000 0x20000>, + <0x240000 0x20000>, + <0x260000 0x20000>; + + gic_v2m0: v2m@280000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x280000 0x1000>; + arm,msi-base-spi = <160>; + arm,msi-num-spis = <32>; + }; + gic_v2m1: v2m@290000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x290000 0x1000>; + arm,msi-base-spi = <192>; + arm,msi-num-spis = <32>; + }; + gic_v2m2: v2m@2a0000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x2a0000 0x1000>; + arm,msi-base-spi = <224>; + arm,msi-num-spis = <32>; + }; + gic_v2m3: v2m@2b0000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x2b0000 0x1000>; + arm,msi-base-spi = <256>; + arm,msi-num-spis = <32>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>; + }; + + odmi: odmi@300000 { + compatible = "marvell,odmi-controller"; + interrupt-controller; + msi-controller; + marvell,odmi-frames = <4>; + reg = <0x300000 0x4000>, + <0x304000 0x4000>, + <0x308000 0x4000>, + <0x30C000 0x4000>; + marvell,spi-base = <128>, <136>, <144>, <152>; + }; + + xor@400000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x400000 0x1000>, + <0x410000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + xor@420000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x420000 0x1000>, + <0x430000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + xor@440000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x440000 0x1000>, + <0x450000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + xor@460000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x460000 0x1000>, + <0x470000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + spi0: spi@510600 { + compatible = "marvell,armada-380-spi"; + reg = <0x510600 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ap_syscon 3>; + status = "disabled"; + }; + + i2c0: i2c@511000 { + compatible = "marvell,mv78230-i2c"; + reg = <0x511000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + timeout-ms = <1000>; + clocks = <&ap_syscon 3>; + status = "disabled"; + }; + + uart0: serial@512000 { + compatible = "snps,dw-apb-uart"; + reg = <0x512000 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <1>; + clocks = <&ap_syscon 3>; + status = "disabled"; + }; + + uart1: serial@512100 { + compatible = "snps,dw-apb-uart"; + reg = <0x512100 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <1>; + clocks = <&ap_syscon 3>; + status = "disabled"; + + }; + + ap_syscon: system-controller@6f4000 { + compatible = "marvell,ap806-system-controller", + "syscon"; + #clock-cells = <1>; + clock-output-names = "ap-cpu-cluster-0", + "ap-cpu-cluster-1", + "ap-fixed", "ap-mss"; + reg = <0x6f4000 0x1000>; + }; + }; + }; +}; diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi new file mode 100644 index 0000000..367138b --- /dev/null +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library 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 (at your option) any later version. + * + * This library 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Device Tree file for Marvell Armada CP110 Master. + */ + +/ { + cp110-master { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + config-space { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges = <0x0 0x0 0xf2000000 0x2000000>; + + cpm_syscon0: system-controller@440000 { + compatible = "marvell,cp110-system-controller0", + "syscon"; + reg = <0x440000 0x1000>; + #clock-cells = <2>; + core-clock-output-names = + "cpm-apll", "cpm-ppv2-core", "cpm-eip", + "cpm-core", "cpm-nand-core"; + gate-clock-output-names = + "cpm-audio", "cpm-communit", "cpm-nand", + "cpm-ppv2", "cpm-sdio", "cpm-mg-domain", + "cpm-mg-core", "cpm-xor1", "cpm-xor0", + "cpm-gop-dp", "none", "cpm-pcie_x10", + "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", + "cpm-sata", "cpm-sata-usb", "cpm-main", + "cpm-sd-mmc", "none", "none", + "cpm-slow-io", "cpm-usb3h0", "cpm-usb3h1", + "cpm-usb3dev", "cpm-eip150", "cpm-eip197"; + }; + + cpm_sata0: sata@540000 { + compatible = "marvell,armada-8k-ahci"; + reg = <0x540000 0x30000>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpm_syscon0 1 15>; + status = "disabled"; + }; + + cpm_usb3_0: usb3@500000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x500000 0x4000>; + dma-coherent; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpm_syscon0 1 22>; + status = "disabled"; + }; + + cpm_usb3_1: usb3@510000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x510000 0x4000>; + dma-coherent; + interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpm_syscon0 1 23>; + status = "disabled"; + }; + + cpm_spi0: spi@700600 { + compatible = "marvell,armada-380-spi"; + reg = <0x700600 0x50>; + #address-cells = <0x1>; + #size-cells = <0x0>; + cell-index = <1>; + clocks = <&cpm_syscon0 0 3>; + status = "disabled"; + }; + + cpm_spi1: spi@700680 { + compatible = "marvell,armada-380-spi"; + reg = <0x700680 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <2>; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + + cpm_i2c0: i2c@701000 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + + cpm_i2c1: i2c@701100 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + }; + + cpm_pcie0: pcie@f2600000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2600000 0 0x10000>, + <0 0xf6f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9000000 0 0xf9000000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + num-lanes = <1>; + clocks = <&cpm_syscon0 1 13>; + status = "disabled"; + }; + + cpm_pcie1: pcie@f2620000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2620000 0 0x10000>, + <0 0xf7f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9010000 0 0xf9010000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf7000000 0 0xf7000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + + num-lanes = <1>; + clocks = <&cpm_syscon0 1 11>; + status = "disabled"; + }; + + cpm_pcie2: pcie@f2640000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2640000 0 0x10000>, + <0 0xf8f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9020000 0 0xf9020000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf8000000 0 0xf8000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + + num-lanes = <1>; + clocks = <&cpm_syscon0 1 12>; + status = "disabled"; + }; + }; +};

Compared to the Armada 3700, the Armada 7K and 8K are much more on the high-end side: they use a dual Cortex-A72 or a quad Cortex-A72, as opposed to the Cortex-A53 for the Armada 3700.
The Armada 7K and 8K also use a fairly unique architecture, internally they are composed of several components:
- One AP (Application Processor), which contains the processor itself and a few core hardware blocks. The AP used in the Armada 7K and 8K is called AP806, and is available in two configurations: dual Cortex-A72 and quad Cortex-A72. - One or two CP (Communication Processor), which contain most of the I/O interfaces (SATA, PCIe, Ethernet, etc.). The 7K family chips have one CP, while the 8K family chips integrate two CPs, providing two times the number of I/O interfaces available in the CP. The CP used in the 7K and 8K is called CP110.
All in all, this gives the following combinations:
- Armada 7020, which is a dual Cortex-A72 with one CP - Armada 7040, which is a quad Cortex-A72 with one CP - Armada 8020, which is a dual Cortex-A72 with two CPs - Armada 8040, which is a quad Cortex-A72 with two CPs
This patch adds basic support for this ARMv8 based SoC into U-Boot. Future patches will integrate other device drivers and board support, starting with the Marvell DB-88F7040 development board.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- arch/arm/Kconfig | 2 +- arch/arm/mach-mvebu/Kconfig | 7 +- arch/arm/mach-mvebu/Makefile | 3 + arch/arm/mach-mvebu/arm64-common.c | 124 ++++++++++++++++++++++++++++ arch/arm/mach-mvebu/armada3700/Makefile | 1 - arch/arm/mach-mvebu/armada3700/cpu.c | 107 ------------------------ arch/arm/mach-mvebu/armada8k/Makefile | 7 ++ arch/arm/mach-mvebu/armada8k/cpu.c | 64 ++++++++++++++ arch/arm/mach-mvebu/include/mach/soc.h | 2 + arch/arm/mach-mvebu/{armada3700 => }/sata.c | 9 ++ 10 files changed, 216 insertions(+), 110 deletions(-) create mode 100644 arch/arm/mach-mvebu/arm64-common.c create mode 100644 arch/arm/mach-mvebu/armada8k/Makefile create mode 100644 arch/arm/mach-mvebu/armada8k/cpu.c rename arch/arm/mach-mvebu/{armada3700 => }/sata.c (77%)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f9d0d2e..61a2fe6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -164,7 +164,7 @@ config KIRKWOOD select CPU_ARM926EJS
config ARCH_MVEBU - bool "Marvell MVEBU family (Armada XP/375/38x)" + bool "Marvell MVEBU family (Armada XP/375/38x/3700/7K/8K)" select OF_CONTROL select OF_SEPARATE select DM diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index bede700..54b3b72 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -31,6 +31,11 @@ config ARMADA_3700 bool select ARM64
+# Armada 7K and 8K are very similar - use only one Kconfig symbol for both +config ARMADA_8K + bool + select ARM64 + # Armada XP/38x SoC types... config MV78230 bool @@ -49,7 +54,7 @@ config DB_88F6820_GP select ARMADA_38X
choice - prompt "Marvell MVEBU (Armada XP/375/38x/3700) board select" + prompt "Armada XP/375/38x/3700/7K/8K board select" optional
config TARGET_CLEARFOG diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 07dc16c..65e90c4 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -7,6 +7,9 @@ ifdef CONFIG_ARM64
obj-$(CONFIG_ARMADA_3700) += armada3700/ +obj-$(CONFIG_ARMADA_8K) += armada8k/ +obj-y += arm64-common.o +obj-y += sata.o
else # CONFIG_ARM64
diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c new file mode 100644 index 0000000..7055a81 --- /dev/null +++ b/arch/arm/mach-mvebu/arm64-common.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2016 Stefan Roese sr@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> +#include <asm/armv8/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * On ARMv8, MBus is not configured in U-Boot. To enable compilation + * of the already implemented drivers, lets add a dummy version of + * this function so that linking does not fail. + */ +const struct mbus_dram_target_info *mvebu_mbus_dram_info(void) +{ + return NULL; +} + +/* DRAM init code ... */ + +static const void *get_memory_reg_prop(const void *fdt, int *lenp) +{ + int offset; + + offset = fdt_path_offset(fdt, "/memory"); + if (offset < 0) + return NULL; + + return fdt_getprop(fdt, offset, "reg", lenp); +} + +int dram_init(void) +{ + const void *fdt = gd->fdt_blob; + const fdt32_t *val; + int ac, sc, len; + + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 0 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); + return -EINVAL; + } + + val = get_memory_reg_prop(fdt, &len); + if (len / sizeof(*val) < ac + sc) + return -EINVAL; + + val += ac; + + gd->ram_size = fdtdec_get_number(val, sc); + + debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); + + return 0; +} + +void dram_init_banksize(void) +{ + const void *fdt = gd->fdt_blob; + const fdt32_t *val; + int ac, sc, cells, len, i; + + val = get_memory_reg_prop(fdt, &len); + if (len < 0) + return; + + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 1 || sc > 2 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); + return; + } + + cells = ac + sc; + + len /= sizeof(*val); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells; + i++, len -= cells) { + gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac); + val += ac; + gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc); + val += sc; + + debug("DRAM bank %d: start = %08lx, size = %08lx\n", + i, (unsigned long)gd->bd->bi_dram[i].start, + (unsigned long)gd->bd->bi_dram[i].size); + } +} + +int arch_cpu_init(void) +{ + /* Nothing to do (yet) */ + return 0; +} + +int arch_early_init_r(void) +{ + struct udevice *dev; + int ret; + + /* Call the comphy code via the MISC uclass driver */ + ret = uclass_get_device(UCLASS_MISC, 0, &dev); + if (ret) { + debug("COMPHY init failed: %d\n", ret); + return -ENODEV; + } + + /* Cause the SATA device to do its early init */ + uclass_first_device(UCLASS_AHCI, &dev); + + return 0; +} diff --git a/arch/arm/mach-mvebu/armada3700/Makefile b/arch/arm/mach-mvebu/armada3700/Makefile index b1fac57..84c69d9 100644 --- a/arch/arm/mach-mvebu/armada3700/Makefile +++ b/arch/arm/mach-mvebu/armada3700/Makefile @@ -5,4 +5,3 @@ #
obj-y = cpu.o -obj-y += sata.o diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c index 7d8f7b8..6499eec 100644 --- a/arch/arm/mach-mvebu/armada3700/cpu.c +++ b/arch/arm/mach-mvebu/armada3700/cpu.c @@ -53,16 +53,6 @@ static struct mm_region mvebu_mem_map[] = {
struct mm_region *mem_map = mvebu_mem_map;
-/* - * On ARMv8, MBus is not configured in U-Boot. To enable compilation - * of the already implemented drivers, lets add a dummy version of - * this function so that linking does not fail. - */ -const struct mbus_dram_target_info *mvebu_mbus_dram_info(void) -{ - return NULL; -} - void reset_cpu(ulong ignored) { /* @@ -89,100 +79,3 @@ u32 get_ref_clk(void) else return 40; } - -/* DRAM init code ... */ - -static const void *get_memory_reg_prop(const void *fdt, int *lenp) -{ - int offset; - - offset = fdt_path_offset(fdt, "/memory"); - if (offset < 0) - return NULL; - - return fdt_getprop(fdt, offset, "reg", lenp); -} - -int dram_init(void) -{ - const void *fdt = gd->fdt_blob; - const fdt32_t *val; - int ac, sc, len; - - ac = fdt_address_cells(fdt, 0); - sc = fdt_size_cells(fdt, 0); - if (ac < 0 || sc < 1 || sc > 2) { - printf("invalid address/size cells\n"); - return -EINVAL; - } - - val = get_memory_reg_prop(fdt, &len); - if (len / sizeof(*val) < ac + sc) - return -EINVAL; - - val += ac; - - gd->ram_size = fdtdec_get_number(val, sc); - - debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); - - return 0; -} - -void dram_init_banksize(void) -{ - const void *fdt = gd->fdt_blob; - const fdt32_t *val; - int ac, sc, cells, len, i; - - val = get_memory_reg_prop(fdt, &len); - if (len < 0) - return; - - ac = fdt_address_cells(fdt, 0); - sc = fdt_size_cells(fdt, 0); - if (ac < 1 || sc > 2 || sc < 1 || sc > 2) { - printf("invalid address/size cells\n"); - return; - } - - cells = ac + sc; - - len /= sizeof(*val); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells; - i++, len -= cells) { - gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac); - val += ac; - gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc); - val += sc; - - debug("DRAM bank %d: start = %08lx, size = %08lx\n", - i, (unsigned long)gd->bd->bi_dram[i].start, - (unsigned long)gd->bd->bi_dram[i].size); - } -} - -int arch_cpu_init(void) -{ - /* Nothing to do (yet) */ - return 0; -} - -int arch_early_init_r(void) -{ - struct udevice *dev; - int ret; - - /* Call the comphy code via the MISC uclass driver */ - ret = uclass_get_device(UCLASS_MISC, 0, &dev); - if (ret) { - debug("COMPHY init failed: %d\n", ret); - return -ENODEV; - } - - /* Cause the SATA device to do its early init */ - uclass_first_device(UCLASS_AHCI, &dev); - - return 0; -} diff --git a/arch/arm/mach-mvebu/armada8k/Makefile b/arch/arm/mach-mvebu/armada8k/Makefile new file mode 100644 index 0000000..84c69d9 --- /dev/null +++ b/arch/arm/mach-mvebu/armada8k/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Stefan Roese sr@denx.de +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c new file mode 100644 index 0000000..036430c --- /dev/null +++ b/arch/arm/mach-mvebu/armada8k/cpu.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 Stefan Roese sr@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> +#include <asm/armv8/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Armada 7k/8k */ +#define MVEBU_RFU_BASE (MVEBU_REGISTER(0x6f0000)) +#define RFU_GLOBAL_SW_RST (MVEBU_RFU_BASE + 0x84) +#define RFU_SW_RESET_OFFSET 0 + +static struct mm_region mvebu_mem_map[] = { + { + /* RAM */ + .phys = 0x0UL, + .virt = 0x0UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, + { + /* SRAM, MMIO regions - AP806 region */ + .phys = 0xf0000000UL, + .virt = 0xf0000000UL, + .size = 0x01000000UL, /* 16MiB internal registers */ + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + }, + { + /* SRAM, MMIO regions - CP110 region */ + .phys = 0xf2000000UL, + .virt = 0xf2000000UL, + .size = 0x02000000UL, /* 32MiB internal registers */ + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + }, + { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = mvebu_mem_map; + +void reset_cpu(ulong ignored) +{ + u32 reg; + + reg = readl(RFU_GLOBAL_SW_RST); + reg &= ~(1 << RFU_SW_RESET_OFFSET); + writel(reg, RFU_GLOBAL_SW_RST); +} diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 063d6cc..731fe65 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -46,6 +46,8 @@ * required for the Linux kernel. */ #define SOC_REGS_PHY_BASE 0xd0000000 +#elif defined(CONFIG_ARMADA_8K) +#define SOC_REGS_PHY_BASE 0xf0000000 #else #define SOC_REGS_PHY_BASE 0xf1000000 #endif diff --git a/arch/arm/mach-mvebu/armada3700/sata.c b/arch/arm/mach-mvebu/sata.c similarity index 77% rename from arch/arm/mach-mvebu/armada3700/sata.c rename to arch/arm/mach-mvebu/sata.c index e0e8381..140a295 100644 --- a/arch/arm/mach-mvebu/armada3700/sata.c +++ b/arch/arm/mach-mvebu/sata.c @@ -19,6 +19,14 @@ __weak int board_ahci_enable(void) return 0; }
+#ifdef CONFIG_ARMADA_8K +/* CP110 has different AHCI port addresses */ +void __iomem *ahci_port_base(void __iomem *base, u32 port) +{ + return base + 0x10000 + (port * 0x10000); +} +#endif + static int mvebu_ahci_probe(struct udevice *dev) { /* @@ -34,6 +42,7 @@ static int mvebu_ahci_probe(struct udevice *dev)
static const struct udevice_id mvebu_ahci_ids[] = { { .compatible = "marvell,armada-3700-ahci" }, + { .compatible = "marvell,armada-8k-ahci" }, { } };

This patch adds basic support for the Marvell Armada 7K DB-88F7040 development board. Supported are the following interfaces: - UART - SPI (incl. SPI NOR) - I2C - USB - SATA / AHCI
Support for other interfaces will follow.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- arch/arm/mach-mvebu/Kconfig | 7 ++ board/Marvell/mvebu_db-88f7040/MAINTAINERS | 6 ++ board/Marvell/mvebu_db-88f7040/Makefile | 7 ++ board/Marvell/mvebu_db-88f7040/board.c | 152 +++++++++++++++++++++++++++++ configs/mvebu_db-88f7040_defconfig | 47 +++++++++ include/configs/mvebu_db-88f7040.h | 133 +++++++++++++++++++++++++ 6 files changed, 352 insertions(+) create mode 100644 board/Marvell/mvebu_db-88f7040/MAINTAINERS create mode 100644 board/Marvell/mvebu_db-88f7040/Makefile create mode 100644 board/Marvell/mvebu_db-88f7040/board.c create mode 100644 configs/mvebu_db-88f7040_defconfig create mode 100644 include/configs/mvebu_db-88f7040.h
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 54b3b72..9bdcdc8 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -73,6 +73,10 @@ config TARGET_DB_88F6820_GP bool "Support DB-88F6820-GP" select DB_88F6820_GP
+config TARGET_MVEBU_DB_88F7040 + bool "Support DB-88F7040 Armada 7040" + select ARMADA_8K + config TARGET_DB_MV784MP_GP bool "Support db-mv784mp-gp" select MV78460 @@ -96,6 +100,7 @@ config SYS_BOARD default "mvebu_db-88f3720" if TARGET_MVEBU_DB_88F3720 default "db-88f6720" if TARGET_DB_88F6720 default "db-88f6820-gp" if TARGET_DB_88F6820_GP + default "mvebu_db-88f7040" if TARGET_MVEBU_DB_88F7040 default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 default "maxbcm" if TARGET_MAXBCM @@ -106,6 +111,7 @@ config SYS_CONFIG_NAME default "mvebu_db-88f3720" if TARGET_MVEBU_DB_88F3720 default "db-88f6720" if TARGET_DB_88F6720 default "db-88f6820-gp" if TARGET_DB_88F6820_GP + default "mvebu_db-88f7040" if TARGET_MVEBU_DB_88F7040 default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 default "maxbcm" if TARGET_MAXBCM @@ -116,6 +122,7 @@ config SYS_VENDOR default "Marvell" if TARGET_MVEBU_DB_88F3720 default "Marvell" if TARGET_DB_88F6720 default "Marvell" if TARGET_DB_88F6820_GP + default "Marvell" if TARGET_MVEBU_DB_88F7040 default "solidrun" if TARGET_CLEARFOG default "Synology" if TARGET_DS414
diff --git a/board/Marvell/mvebu_db-88f7040/MAINTAINERS b/board/Marvell/mvebu_db-88f7040/MAINTAINERS new file mode 100644 index 0000000..820461b --- /dev/null +++ b/board/Marvell/mvebu_db-88f7040/MAINTAINERS @@ -0,0 +1,6 @@ +MVEBU_DB_88F7040 BOARD +M: Stefan Roese sr@denx.de +S: Maintained +F: board/Marvell/mvebu_db-88f7040/ +F: include/configs/mvebu_db-88f7040.h +F: configs/mvebu_db-88f7040_defconfig diff --git a/board/Marvell/mvebu_db-88f7040/Makefile b/board/Marvell/mvebu_db-88f7040/Makefile new file mode 100644 index 0000000..ed39738 --- /dev/null +++ b/board/Marvell/mvebu_db-88f7040/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Stefan Roese sr@denx.de +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := board.o diff --git a/board/Marvell/mvebu_db-88f7040/board.c b/board/Marvell/mvebu_db-88f7040/board.c new file mode 100644 index 0000000..48bd55c --- /dev/null +++ b/board/Marvell/mvebu_db-88f7040/board.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2016 Stefan Roese sr@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* IO expander I2C device */ +#define I2C_IO_EXP_ADDR 0x21 +#define I2C_IO_CFG_REG_0 0x6 +#define I2C_IO_DATA_OUT_REG_0 0x2 +/* VBus enable */ +#define I2C_IO_REG_0_USB_H0_OFF 0 +#define I2C_IO_REG_0_USB_H1_OFF 1 +#define I2C_IO_REG_VBUS ((1 << I2C_IO_REG_0_USB_H0_OFF) | \ + (1 << I2C_IO_REG_0_USB_H1_OFF)) +/* Current limit */ +#define I2C_IO_REG_0_USB_H0_CL 4 +#define I2C_IO_REG_0_USB_H1_CL 5 +#define I2C_IO_REG_CL ((1 << I2C_IO_REG_0_USB_H0_CL) | \ + (1 << I2C_IO_REG_0_USB_H1_CL)) + +static int usb_enabled = 0; + +/* Board specific xHCI dis-/enable code */ + +/* + * Set USB VBUS signals (via I2C IO expander/GPIO) as output and set + * output value as disabled + * + * Set USB Current Limit signals (via I2C IO expander/GPIO) as output + * and set output value as enabled + */ +int board_xhci_config(void) +{ + struct udevice *dev; + int ret; + u8 buf[8]; + + /* Configure IO exander PCA9555: 7bit address 0x21 */ + ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev); + if (ret) { + printf("Cannot find PCA9555: %d\n", ret); + return 0; + } + + /* + * Read configuration (direction) and set VBUS pin as output + * (reset pin = output) + */ + ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1); + if (ret) { + printf("Failed to read IO expander value via I2C\n"); + return -EIO; + } + buf[0] &= ~I2C_IO_REG_VBUS; + buf[0] &= ~I2C_IO_REG_CL; + ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1); + if (ret) { + printf("Failed to set IO expander via I2C\n"); + return -EIO; + } + + /* Read output value and configure it */ + ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); + if (ret) { + printf("Failed to read IO expander value via I2C\n"); + return -EIO; + } + buf[0] &= ~I2C_IO_REG_VBUS; + buf[0] |= I2C_IO_REG_CL; + ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); + if (ret) { + printf("Failed to set IO expander via I2C\n"); + return -EIO; + } + + mdelay(500); /* required delay to let output value settle */ + + return 0; +} + +int board_xhci_enable(void) +{ + struct udevice *dev; + int ret; + u8 buf[8]; + + /* + * This function enables all USB ports simultaniously, + * it only needs to get called once + */ + if (usb_enabled) + return 0; + + /* Configure IO exander PCA9555: 7bit address 0x21 */ + ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev); + if (ret) { + printf("Cannot find PCA9555: %d\n", ret); + return 0; + } + + /* Read VBUS output value */ + ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); + if (ret) { + printf("Failed to read IO expander value via I2C\n"); + return -EIO; + } + + /* Enable VBUS power: Set output value of VBUS pin as enabled */ + buf[0] |= I2C_IO_REG_VBUS; + ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1); + if (ret) { + printf("Failed to set IO expander via I2C\n"); + return -EIO; + } + + mdelay(500); /* required delay to let output value settle */ + usb_enabled = 1; + + return 0; +} + +int board_early_init_f(void) +{ + /* Nothing to do (yet), perhaps later some pin-muxing etc */ + + return 0; +} + +int board_init(void) +{ + /* adress of boot parameters */ + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + + return 0; +} + +int board_late_init(void) +{ + /* Pre-configure the USB ports (overcurrent, VBus) */ + board_xhci_config(); + + return 0; +} diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig new file mode 100644 index 0000000..4d68bdc --- /dev/null +++ b/configs/mvebu_db-88f7040_defconfig @@ -0,0 +1,47 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_MVEBU_DB_88F7040=y +CONFIG_DEFAULT_DEVICE_TREE="armada-7040-db" +CONFIG_AHCI=y +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_BLOCK_CACHE=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_MVTWSI=y +CONFIG_MISC=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_PHYLIB=y +CONFIG_MVEBU_COMPHY_SUPPORT=y +# CONFIG_SPL_SERIAL_PRESENT is not set +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_BASE=0xf0512000 +CONFIG_DEBUG_UART_CLOCK=200000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y diff --git a/include/configs/mvebu_db-88f7040.h b/include/configs/mvebu_db-88f7040.h new file mode 100644 index 0000000..cfb0191 --- /dev/null +++ b/include/configs/mvebu_db-88f7040.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2016 Stefan Roese sr@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CONFIG_MVEBU_DB_88F7040_H +#define _CONFIG_MVEBU_DB_88F7040_H + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_SYS_TCLK 250000000 /* 250MHz */ + +#define CONFIG_DISPLAY_BOARDINFO_LATE +#define CONFIG_ARCH_EARLY_INIT_R +#define CONFIG_BOARD_LATE_INIT + +#define CONFIG_SYS_TEXT_BASE 0x00000000 + +/* additions for new ARM relocation support */ +#define CONFIG_SYS_SDRAM_BASE 0x00000000 + +#define CONFIG_NR_DRAM_BANKS 1 + +/* auto boot */ +#define CONFIG_PREBOOT + +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \ + 115200, 230400, 460800, 921600 } + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS /* enable memory tag */ + +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ + +sizeof(CONFIG_SYS_PROMPT) + 16) /* Print Buff */ + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN (4 << 20) /* 4MiB for malloc() */ + +/* + * Other required minimal configurations + */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_AUTO_COMPLETE +#define CONFIG_CMDLINE_EDITING +#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_ARCH_CPU_INIT /* call arch_cpu_init() */ +#define CONFIG_BOARD_EARLY_INIT_F /* call board_init_f for early inits */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */ +#define CONFIG_SYS_MEMTEST_START 0x00800000 /* 8M */ +#define CONFIG_SYS_MEMTEST_END 0x00ffffff /*(_16M -1) */ +#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */ +#define CONFIG_SYS_MAXARGS 32 /* max number of command args */ + +#define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */ +#define CONFIG_SYS_ALT_MEMTEST + +/* End of 16M scrubbed by training in bootrom */ +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0xFF0000) + +/* + * SPI Flash configuration + */ +#define CONFIG_KIRKWOOD_SPI +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 + +/* SPI NOR flash default params, used by sf commands */ +#define CONFIG_SF_DEFAULT_SPEED 1000000 +#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0 +#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE + +/* Environment in SPI NOR flash */ +#define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */ +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_OFFSET 0x180000 /* as Marvell U-Boot version */ +#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ +#define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */ + +/* USB 2.0 */ +#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 + +/* USB 3.0 */ +#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3 + +#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \ + CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) + +/* USB ethernet */ +#define CONFIG_USB_HOST_ETHER +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_MCS7830 +#define CONFIG_USB_ETHER_RTL8152 +#define CONFIG_USB_ETHER_SMSC95XX + +/* + * SATA/SCSI/AHCI configuration + */ +#define CONFIG_SCSI +#define CONFIG_SCSI_AHCI +#define CONFIG_SCSI_AHCI_PLAT +#define CONFIG_LIBATA +#define CONFIG_LBA48 +#define CONFIG_SYS_64BIT_LBA + +#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 +#define CONFIG_SYS_SCSI_MAX_LUN 1 +#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ + CONFIG_SYS_SCSI_MAX_LUN) + +#define CONFIG_SUPPORT_VFAT + +/* DISK Partition support */ +#define CONFIG_EFI_PARTITION +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION /* Experimental */ + +#define CONFIG_CMD_PART +#define CONFIG_PARTITION_UUIDS + +#endif /* _CONFIG_MVEBU_DB_88F7040_H */

The clock frequency needs to be provided in the DT. Otherwise the driver won't start in U-Boot.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- arch/arm/dts/armada-ap806.dtsi | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/dts/armada-ap806.dtsi b/arch/arm/dts/armada-ap806.dtsi index 20d256b..d315b29 100644 --- a/arch/arm/dts/armada-ap806.dtsi +++ b/arch/arm/dts/armada-ap806.dtsi @@ -202,6 +202,7 @@ reg-io-width = <1>; clocks = <&ap_syscon 3>; status = "disabled"; + clock-frequency = <200000000>; };
uart1: serial@512100 {

This patch adds the COMPHY device tree nodes that are still missing to the Armada 7K/8K dts files.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- arch/arm/dts/armada-7040-db.dts | 40 +++++++++++++++++++++++++++++++++++ arch/arm/dts/armada-cp110-master.dtsi | 28 ++++++++++++++++++++++++ 2 files changed, 68 insertions(+)
diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts index 070b589..df0c327 100644 --- a/arch/arm/dts/armada-7040-db.dts +++ b/arch/arm/dts/armada-7040-db.dts @@ -146,3 +146,43 @@ &cpm_usb3_1 { status = "okay"; }; + +&comphy_cp110 { + phy0 { + phy-type = <PHY_TYPE_SGMII2>; + phy-speed = <PHY_SPEED_3_125G>; + }; + + phy1 { + phy-type = <PHY_TYPE_USB3_HOST0>; + phy-speed = <PHY_SPEED_5G>; + }; + + phy2 { + phy-type = <PHY_TYPE_SGMII0>; + phy-speed = <PHY_SPEED_1_25G>; + }; + + phy3 { + phy-type = <PHY_TYPE_SATA1>; + phy-speed = <PHY_SPEED_5G>; + }; + + phy4 { + phy-type = <PHY_TYPE_USB3_HOST1>; + phy-speed = <PHY_SPEED_5G>; + }; + + phy5 { + phy-type = <PHY_TYPE_PEX2>; + phy-speed = <PHY_SPEED_5G>; + }; +}; + +&utmi0 { + status = "okay"; +}; + +&utmi1 { + status = "okay"; +}; diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi index 367138b..7da98bf 100644 --- a/arch/arm/dts/armada-cp110-master.dtsi +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -44,6 +44,8 @@ * Device Tree file for Marvell Armada CP110 Master. */
+#include <dt-bindings/comphy/comphy_data.h> + / { cp110-master { #address-cells = <2>; @@ -146,6 +148,32 @@ clocks = <&cpm_syscon0 1 21>; status = "disabled"; }; + + comphy_cp110: comphy@441000 { + compatible = "marvell,mvebu-comphy", "marvell,comphy-cp110"; + reg = <0x441000 0x8>, + <0x120000 0x8>; + mux-bitcount = <4>; + max-lanes = <6>; + }; + + utmi0: utmi@580000 { + compatible = "marvell,mvebu-utmi-2.6.0"; + reg = <0x580000 0x1000>, /* utmi-unit */ + <0x440420 0x4>, /* usb-cfg */ + <0x440440 0x4>; /* utmi-cfg */ + utmi-port = <UTMI_PHY_TO_USB_HOST0>; + status = "disabled"; + }; + + utmi1: utmi@581000 { + compatible = "marvell,mvebu-utmi-2.6.0"; + reg = <0x581000 0x1000>, /* utmi-unit */ + <0x440420 0x4>, /* usb-cfg */ + <0x440444 0x4>; /* utmi-cfg */ + utmi-port = <UTMI_PHY_TO_USB_HOST1>; + status = "disabled"; + }; };
cpm_pcie0: pcie@f2600000 {

Add I2C and SPI aliases to enable usage in U-Boot.
Signed-off-by: Stefan Roese sr@denx.de Cc: Nadav Haklai nadavh@marvell.com Cc: Neta Zur Hershkovits neta@marvell.com Cc: Kostya Porotchkin kostap@marvell.com Cc: Omri Itach omrii@marvell.com Cc: Igal Liberman igall@marvell.com Cc: Haim Boot hayim@marvell.com Cc: Hanna Hawa hannah@marvell.com --- arch/arm/dts/armada-7040-db.dts | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts index df0c327..7d0059a 100644 --- a/arch/arm/dts/armada-7040-db.dts +++ b/arch/arm/dts/armada-7040-db.dts @@ -55,6 +55,11 @@ stdout-path = "serial0:115200n8"; };
+ aliases { + i2c0 = &cpm_i2c0; + spi0 = &cpm_spi1; + }; + memory@00000000 { device_type = "memory"; reg = <0x0 0x0 0x0 0x80000000>;
participants (1)
-
Stefan Roese