Skip to content

Commit 5b026a9

Browse files
Mrinmay SarkarMani-Sadhasivam
authored andcommitted
PCI: qcom-ep: Add support for firmware-managed PCIe Endpoint
Some Qualcomm platforms use firmware to manage PCIe resources such as clocks, resets, and PHY through the SCMI interface. In these cases, the Linux driver should not perform resource enable or disable operations directly. So introduce a `firmware_managed` flag in 'struct qcom_pcie_ep_cfg', and set it to true for SA8255p SoC. When this flag is set, the driver will skip the resource handling and rely on runtime PM APIs to let the firmware handle the resources with the help of power domain. Signed-off-by: Mrinmay Sarkar <mrinmay.sarkar@oss.qualcomm.com> [mani: reworded description and tiny code cleanup] Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> Link: https://patch.msgid.link/20260106-firmware_managed_ep-v5-2-1933432127ec@oss.qualcomm.com
1 parent 20165a8 commit 5b026a9

1 file changed

Lines changed: 53 additions & 8 deletions

File tree

drivers/pci/controller/dwc/pcie-qcom-ep.c

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,13 @@ enum qcom_pcie_ep_link_status {
168168
* @hdma_support: HDMA support on this SoC
169169
* @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache snooping
170170
* @disable_mhi_ram_parity_check: Disable MHI RAM data parity error check
171+
* @firmware_managed: Set if the controller is firmware managed
171172
*/
172173
struct qcom_pcie_ep_cfg {
173174
bool hdma_support;
174175
bool override_no_snoop;
175176
bool disable_mhi_ram_parity_check;
177+
bool firmware_managed;
176178
};
177179

178180
/**
@@ -377,6 +379,14 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
377379

378380
static void qcom_pcie_disable_resources(struct qcom_pcie_ep *pcie_ep)
379381
{
382+
struct device *dev = pcie_ep->pci.dev;
383+
384+
pm_runtime_put(dev);
385+
386+
/* Skip resource disablement if controller is firmware-managed */
387+
if (pcie_ep->cfg && pcie_ep->cfg->firmware_managed)
388+
return;
389+
380390
icc_set_bw(pcie_ep->icc_mem, 0, 0);
381391
phy_power_off(pcie_ep->phy);
382392
phy_exit(pcie_ep->phy);
@@ -390,12 +400,24 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
390400
u32 val, offset;
391401
int ret;
392402

403+
ret = pm_runtime_resume_and_get(dev);
404+
if (ret < 0) {
405+
dev_err(dev, "Failed to enable device: %d\n", ret);
406+
return ret;
407+
}
408+
409+
/* Skip resource enablement if controller is firmware-managed */
410+
if (pcie_ep->cfg && pcie_ep->cfg->firmware_managed)
411+
goto skip_resources_enable;
412+
393413
ret = qcom_pcie_enable_resources(pcie_ep);
394414
if (ret) {
395415
dev_err(dev, "Failed to enable resources: %d\n", ret);
416+
pm_runtime_put(dev);
396417
return ret;
397418
}
398419

420+
skip_resources_enable:
399421
/* Perform cleanup that requires refclk */
400422
pci_epc_deinit_notify(pci->ep.epc);
401423
dw_pcie_ep_cleanup(&pci->ep);
@@ -630,6 +652,17 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,
630652
return ret;
631653
}
632654

655+
pcie_ep->reset = devm_gpiod_get(dev, "reset", GPIOD_IN);
656+
if (IS_ERR(pcie_ep->reset))
657+
return PTR_ERR(pcie_ep->reset);
658+
659+
pcie_ep->wake = devm_gpiod_get_optional(dev, "wake", GPIOD_OUT_LOW);
660+
if (IS_ERR(pcie_ep->wake))
661+
return PTR_ERR(pcie_ep->wake);
662+
663+
if (pcie_ep->cfg && pcie_ep->cfg->firmware_managed)
664+
return 0;
665+
633666
pcie_ep->num_clks = devm_clk_bulk_get_all(dev, &pcie_ep->clks);
634667
if (pcie_ep->num_clks < 0) {
635668
dev_err(dev, "Failed to get clocks\n");
@@ -640,14 +673,6 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,
640673
if (IS_ERR(pcie_ep->core_reset))
641674
return PTR_ERR(pcie_ep->core_reset);
642675

643-
pcie_ep->reset = devm_gpiod_get(dev, "reset", GPIOD_IN);
644-
if (IS_ERR(pcie_ep->reset))
645-
return PTR_ERR(pcie_ep->reset);
646-
647-
pcie_ep->wake = devm_gpiod_get_optional(dev, "wake", GPIOD_OUT_LOW);
648-
if (IS_ERR(pcie_ep->wake))
649-
return PTR_ERR(pcie_ep->wake);
650-
651676
pcie_ep->phy = devm_phy_optional_get(dev, "pciephy");
652677
if (IS_ERR(pcie_ep->phy))
653678
ret = PTR_ERR(pcie_ep->phy);
@@ -874,6 +899,12 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)
874899

875900
platform_set_drvdata(pdev, pcie_ep);
876901

902+
pm_runtime_get_noresume(dev);
903+
pm_runtime_set_active(dev);
904+
ret = devm_pm_runtime_enable(dev);
905+
if (ret)
906+
return ret;
907+
877908
ret = qcom_pcie_ep_get_resources(pdev, pcie_ep);
878909
if (ret)
879910
return ret;
@@ -894,6 +925,12 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)
894925
goto err_disable_irqs;
895926
}
896927

928+
ret = pm_runtime_put_sync(dev);
929+
if (ret < 0) {
930+
dev_err(dev, "Failed to suspend device: %d\n", ret);
931+
goto err_disable_irqs;
932+
}
933+
897934
pcie_ep->debugfs = debugfs_create_dir(name, NULL);
898935
qcom_pcie_ep_init_debugfs(pcie_ep);
899936

@@ -930,7 +967,15 @@ static const struct qcom_pcie_ep_cfg cfg_1_34_0 = {
930967
.disable_mhi_ram_parity_check = true,
931968
};
932969

970+
static const struct qcom_pcie_ep_cfg cfg_1_34_0_fw_managed = {
971+
.hdma_support = true,
972+
.override_no_snoop = true,
973+
.disable_mhi_ram_parity_check = true,
974+
.firmware_managed = true,
975+
};
976+
933977
static const struct of_device_id qcom_pcie_ep_match[] = {
978+
{ .compatible = "qcom,sa8255p-pcie-ep", .data = &cfg_1_34_0_fw_managed},
934979
{ .compatible = "qcom,sa8775p-pcie-ep", .data = &cfg_1_34_0},
935980
{ .compatible = "qcom,sdx55-pcie-ep", },
936981
{ .compatible = "qcom,sm8450-pcie-ep", },

0 commit comments

Comments
 (0)