Skip to content

Commit 0e0b45a

Browse files
floatiousbjorn-helgaas
authored andcommitted
PCI: dw-rockchip: Enumerate endpoints based on dll_link_up IRQ
Most boards using the pcie-dw-rockchip PCIe controller lack standard hotplug support. Thus, when an endpoint is attached to the SoC, users have to rescan the bus manually to enumerate the device. This can be avoided by using the 'dll_link_up' interrupt in the combined system interrupt 'sys'. Once the 'dll_link_up' IRQ is received, the bus underneath the host bridge is scanned to enumerate PCIe endpoint devices. This implements the same functionality that was implemented in the DWC based pcie-qcom driver in 4581403 ("PCI: qcom: Enumerate endpoints based on Link up event in 'global_irq' interrupt"). The Root Complex specific device tree binding for pcie-dw-rockchip already has the 'sys' interrupt marked as required, so there is no need to update the device tree binding. This also means that we can request the 'sys' IRQ unconditionally. Link: https://lore.kernel.org/r/20241127145041.3531400-2-cassel@kernel.org Signed-off-by: Niklas Cassel <cassel@kernel.org> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log, squash Pei Xiao's redundant dev_err() fix from https://lore.kernel.org/r/327718207d3cd72847c079ff9d56eb246744c182.1736126067.git.xiaopei01@kylinos.cn, squash Niklas's #define change from https://lore.kernel.org/r/20250103095812.2408364-2-cassel@kernel.org] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
1 parent f063901 commit 0e0b45a

File tree

1 file changed

+60
-8
lines changed

1 file changed

+60
-8
lines changed

drivers/pci/controller/dwc/pcie-dw-rockchip.c

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,34 @@ static const struct dw_pcie_ops dw_pcie_ops = {
389389
.stop_link = rockchip_pcie_stop_link,
390390
};
391391

392+
static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)
393+
{
394+
struct rockchip_pcie *rockchip = arg;
395+
struct dw_pcie *pci = &rockchip->pci;
396+
struct dw_pcie_rp *pp = &pci->pp;
397+
struct device *dev = pci->dev;
398+
u32 reg, val;
399+
400+
reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC);
401+
rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC);
402+
403+
dev_dbg(dev, "PCIE_CLIENT_INTR_STATUS_MISC: %#x\n", reg);
404+
dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip));
405+
406+
if (reg & PCIE_RDLH_LINK_UP_CHGED) {
407+
val = rockchip_pcie_get_ltssm(rockchip);
408+
if ((val & PCIE_LINKUP) == PCIE_LINKUP) {
409+
dev_dbg(dev, "Received Link up event. Starting enumeration!\n");
410+
/* Rescan the bus to enumerate endpoint devices */
411+
pci_lock_rescan_remove();
412+
pci_rescan_bus(pp->bridge->bus);
413+
pci_unlock_rescan_remove();
414+
}
415+
}
416+
417+
return IRQ_HANDLED;
418+
}
419+
392420
static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg)
393421
{
394422
struct rockchip_pcie *rockchip = arg;
@@ -418,14 +446,29 @@ static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg)
418446
return IRQ_HANDLED;
419447
}
420448

421-
static int rockchip_pcie_configure_rc(struct rockchip_pcie *rockchip)
449+
static int rockchip_pcie_configure_rc(struct platform_device *pdev,
450+
struct rockchip_pcie *rockchip)
422451
{
452+
struct device *dev = &pdev->dev;
423453
struct dw_pcie_rp *pp;
454+
int irq, ret;
424455
u32 val;
425456

426457
if (!IS_ENABLED(CONFIG_PCIE_ROCKCHIP_DW_HOST))
427458
return -ENODEV;
428459

460+
irq = platform_get_irq_byname(pdev, "sys");
461+
if (irq < 0)
462+
return irq;
463+
464+
ret = devm_request_threaded_irq(dev, irq, NULL,
465+
rockchip_pcie_rc_sys_irq_thread,
466+
IRQF_ONESHOT, "pcie-sys-rc", rockchip);
467+
if (ret) {
468+
dev_err(dev, "failed to request PCIe sys IRQ\n");
469+
return ret;
470+
}
471+
429472
/* LTSSM enable control mode */
430473
val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE);
431474
rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
@@ -436,7 +479,17 @@ static int rockchip_pcie_configure_rc(struct rockchip_pcie *rockchip)
436479
pp = &rockchip->pci.pp;
437480
pp->ops = &rockchip_pcie_host_ops;
438481

439-
return dw_pcie_host_init(pp);
482+
ret = dw_pcie_host_init(pp);
483+
if (ret) {
484+
dev_err(dev, "failed to initialize host\n");
485+
return ret;
486+
}
487+
488+
/* unmask DLL up/down indicator */
489+
val = HIWORD_UPDATE(PCIE_RDLH_LINK_UP_CHGED, 0);
490+
rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_INTR_MASK_MISC);
491+
492+
return ret;
440493
}
441494

442495
static int rockchip_pcie_configure_ep(struct platform_device *pdev,
@@ -450,14 +503,12 @@ static int rockchip_pcie_configure_ep(struct platform_device *pdev,
450503
return -ENODEV;
451504

452505
irq = platform_get_irq_byname(pdev, "sys");
453-
if (irq < 0) {
454-
dev_err(dev, "missing sys IRQ resource\n");
506+
if (irq < 0)
455507
return irq;
456-
}
457508

458509
ret = devm_request_threaded_irq(dev, irq, NULL,
459510
rockchip_pcie_ep_sys_irq_thread,
460-
IRQF_ONESHOT, "pcie-sys", rockchip);
511+
IRQF_ONESHOT, "pcie-sys-ep", rockchip);
461512
if (ret) {
462513
dev_err(dev, "failed to request PCIe sys IRQ\n");
463514
return ret;
@@ -491,7 +542,8 @@ static int rockchip_pcie_configure_ep(struct platform_device *pdev,
491542
pci_epc_init_notify(rockchip->pci.ep.epc);
492543

493544
/* unmask DLL up/down indicator and hot reset/link-down reset */
494-
rockchip_pcie_writel_apb(rockchip, 0x60000, PCIE_CLIENT_INTR_MASK_MISC);
545+
val = HIWORD_UPDATE(PCIE_RDLH_LINK_UP_CHGED | PCIE_LINK_REQ_RST_NOT_INT, 0);
546+
rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_INTR_MASK_MISC);
495547

496548
return ret;
497549
}
@@ -553,7 +605,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
553605

554606
switch (data->mode) {
555607
case DW_PCIE_RC_TYPE:
556-
ret = rockchip_pcie_configure_rc(rockchip);
608+
ret = rockchip_pcie_configure_rc(pdev, rockchip);
557609
if (ret)
558610
goto deinit_clk;
559611
break;

0 commit comments

Comments
 (0)