drivers/pci/pci_mvebu: Fix for boards with X4 lanes
authorPhil Sutter <phil@nwl.cc>
Fri, 25 Dec 2015 13:41:20 +0000 (14:41 +0100)
committerStefan Roese <sr@denx.de>
Thu, 14 Jan 2016 13:08:59 +0000 (14:08 +0100)
Armada XP has support for X4 lanes, boards specify this in their
serdes_cfg. During PEX init in high_speed_env_lib.c, the configuration
is stored in GEN_PURP_RES_2_REG.

When enumerating PEX, subsequent interfaces of an X4 lane must be
skipped. Otherwise the enumeration hangs up the board.

The way this is implemented here is not exactly beautiful, but it mimics
how Marvell's BSP does it. Alternatively we could get the information
using board_serdes_cfg_get(), but that won't lead to clean code, either.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Stefan Roese <sr@denx.de>
Reviewed-by: Tom Rini <trini@konsulko.com>
arch/arm/mach-mvebu/include/mach/soc.h
drivers/pci/pci_mvebu.c

index c696fc6cec6817a666fb59bcc93ec67015960fd0..9f6a2a407e3762069503f262a01e54d32bcaad59 100644 (file)
@@ -96,6 +96,8 @@
 #define MVCPU_WIN_ENABLE       CPU_WIN_ENABLE
 #define MVCPU_WIN_DISABLE      CPU_WIN_DISABLE
 
+#define COMPHY_REFCLK_ALIGNMENT        (MVEBU_REGISTER(0x182f8))
+
 /* BootROM error register (also includes some status infos) */
 #define CONFIG_BOOTROM_ERR_REG (MVEBU_REGISTER(0x182d0))
 #define BOOTROM_ERR_MODE_OFFS  28
index fd2744dbd4e97c4dec0f9a0149c7fd7dc054f329..4eedfe1cbb56e5e9289f282b9e2b8a20e6cd4808 100644 (file)
@@ -155,6 +155,14 @@ static void mvebu_get_port_lane(struct mvebu_pcie *pcie, int pex_idx,
 }
 #endif
 
+static int mvebu_pex_unit_is_x4(int pex_idx)
+{
+       int pex_unit = pex_idx < 9 ? pex_idx >> 2 : 3;
+       u32 mask = (0x0f << (pex_unit * 8));
+
+       return (readl(COMPHY_REFCLK_ALIGNMENT) & mask) == mask;
+}
+
 static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
 {
        u32 val;
@@ -419,5 +427,11 @@ void pci_init_board(void)
                writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
 
                bus = hose->last_busno + 1;
+
+               /* need to skip more for X4 links, otherwise scan will hang */
+               if (mvebu_soc_family() == MVEBU_SOC_AXP) {
+                       if (mvebu_pex_unit_is_x4(i))
+                               i += 3;
+               }
        }
 }