aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyder Lee <ryder.lee@mediatek.com>2017-08-10 02:34:54 -0400
committerBjorn Helgaas <bhelgaas@google.com>2017-08-30 09:23:55 -0400
commite10b7a184ccf883a456c8683fa2e53eddd3aeb9c (patch)
tree8191e1844128b43883c44232b51e957154bf26b5
parent608fcac7ce31b9644bf0e71810f5a033693c17b0 (diff)
PCI: mediatek: Use readl_poll_timeout() to wait for Gen2 training
Wait for Gen2 training with readl_poll_timeout(), and simplify the hardware assert logical by merging it into a new mtk_pcie_startup_port() interface. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/host/pcie-mediatek.c52
1 files changed, 22 insertions, 30 deletions
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index 9c9f89bcf24c..f4e42266eaa7 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/clk.h> 17#include <linux/clk.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/iopoll.h>
19#include <linux/kernel.h> 20#include <linux/kernel.h>
20#include <linux/of_address.h> 21#include <linux/of_address.h>
21#include <linux/of_pci.h> 22#include <linux/of_pci.h>
@@ -113,11 +114,6 @@ struct mtk_pcie {
113 struct list_head ports; 114 struct list_head ports;
114}; 115};
115 116
116static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
117{
118 return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
119}
120
121static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie) 117static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
122{ 118{
123 struct device *dev = pcie->dev; 119 struct device *dev = pcie->dev;
@@ -171,12 +167,30 @@ static struct pci_ops mtk_pcie_ops = {
171 .write = pci_generic_config_write, 167 .write = pci_generic_config_write,
172}; 168};
173 169
174static void mtk_pcie_configure_rc(struct mtk_pcie_port *port) 170static int mtk_pcie_startup_port(struct mtk_pcie_port *port)
175{ 171{
176 struct mtk_pcie *pcie = port->pcie; 172 struct mtk_pcie *pcie = port->pcie;
177 u32 func = PCI_FUNC(port->index << 3); 173 u32 func = PCI_FUNC(port->index << 3);
178 u32 slot = PCI_SLOT(port->index << 3); 174 u32 slot = PCI_SLOT(port->index << 3);
179 u32 val; 175 u32 val;
176 int err;
177
178 /* assert port PERST_N */
179 val = readl(pcie->base + PCIE_SYS_CFG);
180 val |= PCIE_PORT_PERST(port->index);
181 writel(val, pcie->base + PCIE_SYS_CFG);
182
183 /* de-assert port PERST_N */
184 val = readl(pcie->base + PCIE_SYS_CFG);
185 val &= ~PCIE_PORT_PERST(port->index);
186 writel(val, pcie->base + PCIE_SYS_CFG);
187
188 /* 100ms timeout value should be enough for Gen1/2 training */
189 err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
190 !!(val & PCIE_PORT_LINKUP), 20,
191 100 * USEC_PER_MSEC);
192 if (err)
193 return -ETIMEDOUT;
180 194
181 /* enable interrupt */ 195 /* enable interrupt */
182 val = readl(pcie->base + PCIE_INT_ENABLE); 196 val = readl(pcie->base + PCIE_INT_ENABLE);
@@ -209,25 +223,8 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
209 writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0), 223 writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
210 pcie->base + PCIE_CFG_ADDR); 224 pcie->base + PCIE_CFG_ADDR);
211 writel(val, pcie->base + PCIE_CFG_DATA); 225 writel(val, pcie->base + PCIE_CFG_DATA);
212}
213 226
214static void mtk_pcie_assert_ports(struct mtk_pcie_port *port) 227 return 0;
215{
216 struct mtk_pcie *pcie = port->pcie;
217 u32 val;
218
219 /* assert port PERST_N */
220 val = readl(pcie->base + PCIE_SYS_CFG);
221 val |= PCIE_PORT_PERST(port->index);
222 writel(val, pcie->base + PCIE_SYS_CFG);
223
224 /* de-assert port PERST_N */
225 val = readl(pcie->base + PCIE_SYS_CFG);
226 val &= ~PCIE_PORT_PERST(port->index);
227 writel(val, pcie->base + PCIE_SYS_CFG);
228
229 /* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
230 msleep(100);
231} 228}
232 229
233static void mtk_pcie_enable_ports(struct mtk_pcie_port *port) 230static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
@@ -250,13 +247,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
250 goto err_phy_on; 247 goto err_phy_on;
251 } 248 }
252 249
253 mtk_pcie_assert_ports(port); 250 if (!mtk_pcie_startup_port(port))
254
255 /* if link up, then setup root port configuration space */
256 if (mtk_pcie_link_up(port)) {
257 mtk_pcie_configure_rc(port);
258 return; 251 return;
259 }
260 252
261 dev_info(dev, "Port%d link down\n", port->index); 253 dev_info(dev, "Port%d link down\n", port->index);
262 254