|
@@ -49,11 +49,20 @@
|
|
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
|
|
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
|
|
#define PCIE_ATU_UPPER_TARGET 0x91C
|
|
#define PCIE_ATU_UPPER_TARGET 0x91C
|
|
|
|
|
|
|
|
+/* LUT registers */
|
|
|
|
+#define PCIE_LUT_BASE 0x80000
|
|
|
|
+#define PCIE_LUT_DBG 0x7FC
|
|
|
|
+
|
|
|
|
+#define PCIE_DBI_RO_WR_EN 0x8bc
|
|
|
|
+
|
|
#define PCIE_LINK_CAP 0x7c
|
|
#define PCIE_LINK_CAP 0x7c
|
|
#define PCIE_LINK_SPEED_MASK 0xf
|
|
#define PCIE_LINK_SPEED_MASK 0xf
|
|
#define PCIE_LINK_STA 0x82
|
|
#define PCIE_LINK_STA 0x82
|
|
|
|
|
|
-#define PCIE_DBI_SIZE (4 * 1024) /* 4K */
|
|
|
|
|
|
+#define LTSSM_STATE_MASK 0x3f
|
|
|
|
+#define LTSSM_PCIE_L0 0x11 /* L0 state */
|
|
|
|
+
|
|
|
|
+#define PCIE_DBI_SIZE 0x100000 /* 1M */
|
|
|
|
|
|
struct ls_pcie {
|
|
struct ls_pcie {
|
|
int idx;
|
|
int idx;
|
|
@@ -103,8 +112,6 @@ struct ls_pcie_info {
|
|
|
|
|
|
/* PEX1/2 Misc Ports Status Register */
|
|
/* PEX1/2 Misc Ports Status Register */
|
|
#define LTSSM_STATE_SHIFT 20
|
|
#define LTSSM_STATE_SHIFT 20
|
|
-#define LTSSM_STATE_MASK 0x3f
|
|
|
|
-#define LTSSM_PCIE_L0 0x11 /* L0 state */
|
|
|
|
|
|
|
|
static int ls_pcie_link_state(struct ls_pcie *pcie)
|
|
static int ls_pcie_link_state(struct ls_pcie *pcie)
|
|
{
|
|
{
|
|
@@ -121,18 +128,18 @@ static int ls_pcie_link_state(struct ls_pcie *pcie)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
#else
|
|
#else
|
|
-#define PCIE_LDBG 0x7FC
|
|
|
|
-
|
|
|
|
static int ls_pcie_link_state(struct ls_pcie *pcie)
|
|
static int ls_pcie_link_state(struct ls_pcie *pcie)
|
|
{
|
|
{
|
|
u32 state;
|
|
u32 state;
|
|
|
|
|
|
- state = readl(pcie->dbi + PCIE_LDBG);
|
|
|
|
- if (state)
|
|
|
|
- return 1;
|
|
|
|
|
|
+ state = readl(pcie->dbi + PCIE_LUT_BASE + PCIE_LUT_DBG) &
|
|
|
|
+ LTSSM_STATE_MASK;
|
|
|
|
+ if (state < LTSSM_PCIE_L0) {
|
|
|
|
+ debug("....PCIe link error. LTSSM=0x%02x.\n", state);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- debug("....PCIe link error.\n");
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return 1;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -148,7 +155,11 @@ static int ls_pcie_link_up(struct ls_pcie *pcie)
|
|
/* Try to download speed to gen1 */
|
|
/* Try to download speed to gen1 */
|
|
cap = readl(pcie->dbi + PCIE_LINK_CAP);
|
|
cap = readl(pcie->dbi + PCIE_LINK_CAP);
|
|
writel((cap & (~PCIE_LINK_SPEED_MASK)) | 1, pcie->dbi + PCIE_LINK_CAP);
|
|
writel((cap & (~PCIE_LINK_SPEED_MASK)) | 1, pcie->dbi + PCIE_LINK_CAP);
|
|
- udelay(2000);
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Notice: the following delay has critical impact on link training
|
|
|
|
+ * if too short (<30ms) the link doesn't get up.
|
|
|
|
+ */
|
|
|
|
+ mdelay(100);
|
|
state = ls_pcie_link_state(pcie);
|
|
state = ls_pcie_link_state(pcie);
|
|
if (state)
|
|
if (state)
|
|
return state;
|
|
return state;
|
|
@@ -250,6 +261,10 @@ static int ls_pcie_addr_valid(struct pci_controller *hose, pci_dev_t d)
|
|
if (PCI_DEV(d) > 0)
|
|
if (PCI_DEV(d) > 0)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ /* Controller does not support multi-function in RC mode */
|
|
|
|
+ if ((PCI_BUS(d) == hose->first_busno) && (PCI_FUNC(d) > 0))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -326,8 +341,12 @@ static void ls_pcie_setup_ctrl(struct ls_pcie *pcie,
|
|
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0);
|
|
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0);
|
|
|
|
|
|
/* program correct class for RC */
|
|
/* program correct class for RC */
|
|
|
|
+ writel(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
|
|
pci_hose_write_config_word(hose, dev, PCI_CLASS_DEVICE,
|
|
pci_hose_write_config_word(hose, dev, PCI_CLASS_DEVICE,
|
|
PCI_CLASS_BRIDGE_PCI);
|
|
PCI_CLASS_BRIDGE_PCI);
|
|
|
|
+#ifndef CONFIG_LS102XA
|
|
|
|
+ writel(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
|
|
int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
|
|
int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
|
|
@@ -416,9 +435,9 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
|
|
}
|
|
}
|
|
|
|
|
|
/* Print the negotiated PCIe link width */
|
|
/* Print the negotiated PCIe link width */
|
|
- pci_hose_read_config_word(hose, dev, PCIE_LINK_STA, &temp16);
|
|
|
|
- printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4,
|
|
|
|
- (temp16 & 0xf), info->regs);
|
|
|
|
|
|
+ pci_hose_read_config_word(hose, pdev, PCIE_LINK_STA, &temp16);
|
|
|
|
+ printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4,
|
|
|
|
+ (temp16 & 0xf), info->regs);
|
|
|
|
|
|
if (ep_mode)
|
|
if (ep_mode)
|
|
return busno;
|
|
return busno;
|