These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / pci / host / pci-imx6.c
index fdb9536..9ce7cd1 100644 (file)
@@ -47,6 +47,8 @@ struct imx6_pcie {
 #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2       0x2
 #define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK       0xf
 
+#define PCIE_RC_LCSR                           0x80
+
 /* PCIe Port Logic registers (memory-mapped) */
 #define PL_OFFSET 0x700
 #define PCIE_PL_PFLR (PL_OFFSET + 0x08)
@@ -72,6 +74,7 @@ struct imx6_pcie {
 
 /* PHY registers (not memory-mapped) */
 #define PCIE_PHY_RX_ASIC_OUT 0x100D
+#define PCIE_PHY_RX_ASIC_OUT_VALID     (1 << 0)
 
 #define PHY_RX_OVRD_IN_LO 0x1005
 #define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
@@ -115,11 +118,7 @@ static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
        val = addr << PCIE_PHY_CTRL_DATA_LOC;
        writel(val, dbi_base + PCIE_PHY_CTRL);
 
-       ret = pcie_phy_poll_ack(dbi_base, 0);
-       if (ret)
-               return ret;
-
-       return 0;
+       return pcie_phy_poll_ack(dbi_base, 0);
 }
 
 /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
@@ -146,11 +145,7 @@ static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
        /* deassert Read signal */
        writel(0x00, dbi_base + PCIE_PHY_CTRL);
 
-       ret = pcie_phy_poll_ack(dbi_base, 0);
-       if (ret)
-               return ret;
-
-       return 0;
+       return pcie_phy_poll_ack(dbi_base, 0);
 }
 
 static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
@@ -335,21 +330,36 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)
 
 static int imx6_pcie_wait_for_link(struct pcie_port *pp)
 {
-       int count = 200;
+       unsigned int retries;
 
-       while (!dw_pcie_link_up(pp)) {
+       for (retries = 0; retries < 200; retries++) {
+               if (dw_pcie_link_up(pp))
+                       return 0;
                usleep_range(100, 1000);
-               if (--count)
-                       continue;
-
-               dev_err(pp->dev, "phy link never came up\n");
-               dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
-                       readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
-                       readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
-               return -EINVAL;
        }
 
-       return 0;
+       dev_err(pp->dev, "phy link never came up\n");
+       dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
+               readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
+               readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
+       return -EINVAL;
+}
+
+static int imx6_pcie_wait_for_speed_change(struct pcie_port *pp)
+{
+       u32 tmp;
+       unsigned int retries;
+
+       for (retries = 0; retries < 200; retries++) {
+               tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+               /* Test if the speed change finished. */
+               if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
+                       return 0;
+               usleep_range(100, 1000);
+       }
+
+       dev_err(pp->dev, "Speed change timeout\n");
+       return -EINVAL;
 }
 
 static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
@@ -359,11 +369,11 @@ static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
        return dw_handle_msi_irq(pp);
 }
 
-static int imx6_pcie_start_link(struct pcie_port *pp)
+static int imx6_pcie_establish_link(struct pcie_port *pp)
 {
        struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
-       uint32_t tmp;
-       int ret, count;
+       u32 tmp;
+       int ret;
 
        /*
         * Force Gen1 operation when starting the link.  In case the link is
@@ -397,29 +407,22 @@ static int imx6_pcie_start_link(struct pcie_port *pp)
        tmp |= PORT_LOGIC_SPEED_CHANGE;
        writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
 
-       count = 200;
-       while (count--) {
-               tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
-               /* Test if the speed change finished. */
-               if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
-                       break;
-               usleep_range(100, 1000);
+       ret = imx6_pcie_wait_for_speed_change(pp);
+       if (ret) {
+               dev_err(pp->dev, "Failed to bring link up!\n");
+               return ret;
        }
 
        /* Make sure link training is finished as well! */
-       if (count)
-               ret = imx6_pcie_wait_for_link(pp);
-       else
-               ret = -EINVAL;
-
+       ret = imx6_pcie_wait_for_link(pp);
        if (ret) {
                dev_err(pp->dev, "Failed to bring link up!\n");
-       } else {
-               tmp = readl(pp->dbi_base + 0x80);
-               dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+               return ret;
        }
 
-       return ret;
+       tmp = readl(pp->dbi_base + PCIE_RC_LCSR);
+       dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+       return 0;
 }
 
 static void imx6_pcie_host_init(struct pcie_port *pp)
@@ -432,7 +435,7 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
 
        dw_pcie_setup_rc(pp);
 
-       imx6_pcie_start_link(pp);
+       imx6_pcie_establish_link(pp);
 
        if (IS_ENABLED(CONFIG_PCI_MSI))
                dw_pcie_msi_init(pp);
@@ -440,19 +443,19 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
 
 static void imx6_pcie_reset_phy(struct pcie_port *pp)
 {
-       uint32_t temp;
+       u32 tmp;
 
-       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp);
-       temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
-                PHY_RX_OVRD_IN_LO_RX_PLL_EN);
-       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp);
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
+       tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+               PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
 
        usleep_range(2000, 3000);
 
-       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp);
-       temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
+       tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
                  PHY_RX_OVRD_IN_LO_RX_PLL_EN);
-       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp);
+       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
 }
 
 static int imx6_pcie_link_up(struct pcie_port *pp)
@@ -501,7 +504,7 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
        pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
        debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
 
-       if (rx_valid & 0x01)
+       if (rx_valid & PCIE_PHY_RX_ASIC_OUT_VALID)
                return 0;
 
        if ((debug_r0 & 0x3f) != 0x0d)
@@ -534,10 +537,11 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 
                ret = devm_request_irq(&pdev->dev, pp->msi_irq,
                                       imx6_pcie_msi_handler,
-                                      IRQF_SHARED, "mx6-pcie-msi", pp);
+                                      IRQF_SHARED | IRQF_NO_THREAD,
+                                      "mx6-pcie-msi", pp);
                if (ret) {
                        dev_err(&pdev->dev, "failed to request MSI irq\n");
-                       return -ENODEV;
+                       return ret;
                }
        }