Skip to content

Commit 40d957e

Browse files
kishonLorenzo Pieralisi
authored andcommitted
PCI: cadence: Add support to start link and verify link status
Add cdns_pcie_ops to start link and verify link status. The registers to start link and to check link status is in Platform specific PCIe wrapper. Add support for platform specific drivers to add callback functions for the PCIe Cadence core to start link and verify link status. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kishon Vijay Abraham I <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Reviewed-by: Rob Herring <[email protected]>
1 parent a8b661e commit 40d957e

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

drivers/pci/controller/cadence/pcie-cadence-ep.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,10 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
357357
{
358358
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
359359
struct cdns_pcie *pcie = &ep->pcie;
360+
struct device *dev = pcie->dev;
360361
struct pci_epf *epf;
361362
u32 cfg;
363+
int ret;
362364

363365
/*
364366
* BIT(0) is hardwired to 1, hence function 0 is always enabled
@@ -369,6 +371,12 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
369371
cfg |= BIT(epf->func_no);
370372
cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, cfg);
371373

374+
ret = cdns_pcie_start_link(pcie);
375+
if (ret) {
376+
dev_err(dev, "Failed to start link\n");
377+
return ret;
378+
}
379+
372380
return 0;
373381
}
374382

drivers/pci/controller/cadence/pcie-cadence-host.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Cadence PCIe host controller driver.
44
// Author: Cyrille Pitchen <[email protected]>
55

6+
#include <linux/delay.h>
67
#include <linux/kernel.h>
78
#include <linux/list_sort.h>
89
#include <linux/of_address.h>
@@ -420,6 +421,23 @@ static int cdns_pcie_host_init(struct device *dev,
420421
return err;
421422
}
422423

424+
static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie)
425+
{
426+
struct device *dev = pcie->dev;
427+
int retries;
428+
429+
/* Check if the link is up or not */
430+
for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
431+
if (cdns_pcie_link_up(pcie)) {
432+
dev_info(dev, "Link up\n");
433+
return 0;
434+
}
435+
usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
436+
}
437+
438+
return -ETIMEDOUT;
439+
}
440+
423441
int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
424442
{
425443
struct device *dev = rc->pcie.dev;
@@ -468,6 +486,16 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
468486

469487
pcie->mem_res = res;
470488

489+
ret = cdns_pcie_start_link(pcie);
490+
if (ret) {
491+
dev_err(dev, "Failed to start link\n");
492+
return ret;
493+
}
494+
495+
ret = cdns_pcie_host_wait_for_link(pcie);
496+
if (ret)
497+
dev_dbg(dev, "PCIe link never came up\n");
498+
471499
for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++)
472500
rc->avail_ib_bar[bar] = true;
473501

drivers/pci/controller/cadence/pcie-cadence.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
#include <linux/pci.h>
1111
#include <linux/phy/phy.h>
1212

13+
/* Parameters for the waiting for link up routine */
14+
#define LINK_WAIT_MAX_RETRIES 10
15+
#define LINK_WAIT_USLEEP_MIN 90000
16+
#define LINK_WAIT_USLEEP_MAX 100000
17+
1318
/*
1419
* Local Management Registers
1520
*/
@@ -245,12 +250,20 @@ enum cdns_pcie_msg_routing {
245250
MSG_ROUTING_GATHER,
246251
};
247252

253+
struct cdns_pcie_ops {
254+
int (*start_link)(struct cdns_pcie *pcie);
255+
void (*stop_link)(struct cdns_pcie *pcie);
256+
bool (*link_up)(struct cdns_pcie *pcie);
257+
};
258+
248259
/**
249260
* struct cdns_pcie - private data for Cadence PCIe controller drivers
250261
* @reg_base: IO mapped register base
251262
* @mem_res: start/end offsets in the physical system memory to map PCI accesses
252263
* @is_rc: tell whether the PCIe controller mode is Root Complex or Endpoint.
253264
* @bus: In Root Complex mode, the bus number
265+
* @ops: Platform specific ops to control various inputs from Cadence PCIe
266+
* wrapper
254267
*/
255268
struct cdns_pcie {
256269
void __iomem *reg_base;
@@ -261,7 +274,7 @@ struct cdns_pcie {
261274
int phy_count;
262275
struct phy **phy;
263276
struct device_link **link;
264-
const struct cdns_pcie_common_ops *ops;
277+
const struct cdns_pcie_ops *ops;
265278
};
266279

267280
/**
@@ -426,6 +439,28 @@ static inline u32 cdns_pcie_ep_fn_readl(struct cdns_pcie *pcie, u8 fn, u32 reg)
426439
return readl(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
427440
}
428441

442+
static inline int cdns_pcie_start_link(struct cdns_pcie *pcie)
443+
{
444+
if (pcie->ops->start_link)
445+
return pcie->ops->start_link(pcie);
446+
447+
return 0;
448+
}
449+
450+
static inline void cdns_pcie_stop_link(struct cdns_pcie *pcie)
451+
{
452+
if (pcie->ops->stop_link)
453+
pcie->ops->stop_link(pcie);
454+
}
455+
456+
static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
457+
{
458+
if (pcie->ops->link_up)
459+
return pcie->ops->link_up(pcie);
460+
461+
return true;
462+
}
463+
429464
#ifdef CONFIG_PCIE_CADENCE_HOST
430465
int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
431466
#else

0 commit comments

Comments
 (0)