On Wed, Nov 27, 2024 at 03:50:42PM +0100, Niklas Cassel wrote: > 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 commit implements the same functionality that was implemented in the > DWC based pcie-qcom driver in commit 4581403f6792 ("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. > > Signed-off-by: Niklas Cassel <cassel@xxxxxxxxxx> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx> - Mani > --- > drivers/pci/controller/dwc/pcie-dw-rockchip.c | 62 +++++++++++++++++-- > 1 file changed, 58 insertions(+), 4 deletions(-) > > diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c > index 1170e1107508..ce4b511bff9b 100644 > --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c > +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c > @@ -389,6 +389,34 @@ static const struct dw_pcie_ops dw_pcie_ops = { > .stop_link = rockchip_pcie_stop_link, > }; > > +static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg) > +{ > + struct rockchip_pcie *rockchip = arg; > + struct dw_pcie *pci = &rockchip->pci; > + struct dw_pcie_rp *pp = &pci->pp; > + struct device *dev = pci->dev; > + u32 reg, val; > + > + reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); > + rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); > + > + dev_dbg(dev, "PCIE_CLIENT_INTR_STATUS_MISC: %#x\n", reg); > + dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip)); > + > + if (reg & PCIE_RDLH_LINK_UP_CHGED) { > + val = rockchip_pcie_get_ltssm(rockchip); > + if ((val & PCIE_LINKUP) == PCIE_LINKUP) { > + dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); > + /* Rescan the bus to enumerate endpoint devices */ > + pci_lock_rescan_remove(); > + pci_rescan_bus(pp->bridge->bus); > + pci_unlock_rescan_remove(); > + } > + } > + > + return IRQ_HANDLED; > +} > + > static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg) > { > struct rockchip_pcie *rockchip = arg; > @@ -418,14 +446,31 @@ static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg) > return IRQ_HANDLED; > } > > -static int rockchip_pcie_configure_rc(struct rockchip_pcie *rockchip) > +static int rockchip_pcie_configure_rc(struct platform_device *pdev, > + struct rockchip_pcie *rockchip) > { > + struct device *dev = &pdev->dev; > struct dw_pcie_rp *pp; > + int irq, ret; > u32 val; > > if (!IS_ENABLED(CONFIG_PCIE_ROCKCHIP_DW_HOST)) > return -ENODEV; > > + irq = platform_get_irq_byname(pdev, "sys"); > + if (irq < 0) { > + dev_err(dev, "missing sys IRQ resource\n"); > + return irq; > + } > + > + ret = devm_request_threaded_irq(dev, irq, NULL, > + rockchip_pcie_rc_sys_irq_thread, > + IRQF_ONESHOT, "pcie-sys-rc", rockchip); > + if (ret) { > + dev_err(dev, "failed to request PCIe sys IRQ\n"); > + return ret; > + } > + > /* LTSSM enable control mode */ > val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); > rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); > @@ -436,7 +481,16 @@ static int rockchip_pcie_configure_rc(struct rockchip_pcie *rockchip) > pp = &rockchip->pci.pp; > pp->ops = &rockchip_pcie_host_ops; > > - return dw_pcie_host_init(pp); > + ret = dw_pcie_host_init(pp); > + if (ret) { > + dev_err(dev, "failed to initialize host\n"); > + return ret; > + } > + > + /* unmask DLL up/down indicator */ > + rockchip_pcie_writel_apb(rockchip, 0x20000, PCIE_CLIENT_INTR_MASK_MISC); > + > + return ret; > } > > static int rockchip_pcie_configure_ep(struct platform_device *pdev, > @@ -457,7 +511,7 @@ static int rockchip_pcie_configure_ep(struct platform_device *pdev, > > ret = devm_request_threaded_irq(dev, irq, NULL, > rockchip_pcie_ep_sys_irq_thread, > - IRQF_ONESHOT, "pcie-sys", rockchip); > + IRQF_ONESHOT, "pcie-sys-ep", rockchip); > if (ret) { > dev_err(dev, "failed to request PCIe sys IRQ\n"); > return ret; > @@ -553,7 +607,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) > > switch (data->mode) { > case DW_PCIE_RC_TYPE: > - ret = rockchip_pcie_configure_rc(rockchip); > + ret = rockchip_pcie_configure_rc(pdev, rockchip); > if (ret) > goto deinit_clk; > break; > -- > 2.47.0 > -- மணிவண்ணன் சதாசிவம்