[PATCH 05/10] PCI: exynos: Add structure to hold resource operations
From: Shradha Todi <hidden>
Date: 2025-05-19 09:29:51
Also in:
linux-devicetree, linux-pci, linux-phy, lkml
Subsystem:
pci driver for samsung exynos, pci native host bridge and endpoint drivers, pci subsystem, the rest · Maintainers:
Jingoo Han, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Helgaas, Linus Torvalds
Some resources might differ based on platforms and we need platform specific functions to initialize or alter them. For better code re-usability, making a separate res_ops which will hold all such function pointers or other resource specific data. Also move common operations for host init into the probe sequence. Suggested-by: Pankaj Dubey <redacted> Signed-off-by: Shradha Todi <redacted> --- drivers/pci/controller/dwc/pci-exynos.c | 105 ++++++++++++++++++------ 1 file changed, 80 insertions(+), 25 deletions(-)
diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c
index 540612e76f4b..b122a2ae8681 100644
--- a/drivers/pci/controller/dwc/pci-exynos.c
+++ b/drivers/pci/controller/dwc/pci-exynos.c@@ -53,6 +53,7 @@ struct samsung_pcie_pdata { struct pci_ops *pci_ops; const struct dw_pcie_ops *dwc_ops; const struct dw_pcie_host_ops *host_ops; + const struct samsung_res_ops *res_ops; }; struct exynos_pcie {
@@ -61,7 +62,13 @@ struct exynos_pcie { const struct samsung_pcie_pdata *pdata; struct clk_bulk_data *clks; struct phy *phy; - struct regulator_bulk_data supplies[2]; + struct regulator_bulk_data *supplies; + int supplies_cnt; +}; + +struct samsung_res_ops { + int (*init_regulator)(struct exynos_pcie *ep); + irqreturn_t (*pcie_irq_handler)(int irq, void *arg); }; static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg)
@@ -74,6 +81,36 @@ static u32 exynos_pcie_readl(void __iomem *base, u32 reg) return readl(base + reg); } +static int samsung_regulator_enable(struct exynos_pcie *ep) +{ + struct device *dev = ep->pci.dev; + int ret; + + if (ep->supplies_cnt == 0) + return 0; + + ret = devm_regulator_bulk_get(dev, ep->supplies_cnt, ep->supplies); + if (ret) + return ret; + + ret = regulator_bulk_enable(ep->supplies_cnt, ep->supplies); + + return ret; +} + +static void samsung_regulator_disable(struct exynos_pcie *ep) +{ + struct device *dev = ep->pci.dev; + int ret; + + if (ep->supplies_cnt == 0) + return; + + ret = regulator_bulk_disable(ep->supplies_cnt, ep->supplies); + if (ret) + dev_warn(dev, "failed to disable regulators: %d\n", ret); +} + static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on) { u32 val;
@@ -244,7 +281,23 @@ static const struct dw_pcie_host_ops exynos_pcie_host_ops = { .init = exynos_pcie_host_init, }; -static int exynos_add_pcie_port(struct exynos_pcie *ep, +static int exynos_init_regulator(struct exynos_pcie *ep) +{ + struct device *dev = ep->pci.dev; + + ep->supplies_cnt = 2; + + ep->supplies = devm_kcalloc(dev, ep->supplies_cnt, sizeof(*ep->supplies), GFP_KERNEL); + if (!ep->supplies) + return -ENOMEM; + + ep->supplies[0].supply = "vdd18"; + ep->supplies[1].supply = "vdd10"; + + return 0; +} + +static int samsung_irq_init(struct exynos_pcie *ep, struct platform_device *pdev) { struct dw_pcie *pci = &ep->pci;
@@ -256,22 +309,15 @@ static int exynos_add_pcie_port(struct exynos_pcie *ep, if (pp->irq < 0) return pp->irq; - ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler, + ret = devm_request_irq(dev, pp->irq, ep->pdata->res_ops->pcie_irq_handler, IRQF_SHARED, "exynos-pcie", ep); if (ret) { dev_err(dev, "failed to request irq\n"); return ret; } - pp->ops = &exynos_pcie_host_ops; pp->msi_irq[0] = -ENODEV; - ret = dw_pcie_host_init(pp); - if (ret) { - dev_err(dev, "failed to initialize host\n"); - return ret; - } - return 0; }
@@ -282,6 +328,11 @@ static const struct dw_pcie_ops exynos_dw_pcie_ops = { .start_link = exynos_pcie_start_link, }; +static const struct samsung_res_ops exynos_res_ops_data = { + .init_regulator = exynos_init_regulator, + .pcie_irq_handler = exynos_pcie_irq_handler, +}; + static int exynos_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev;
@@ -313,28 +364,31 @@ static int exynos_pcie_probe(struct platform_device *pdev) if (ret < 0) return ret; - ep->supplies[0].supply = "vdd18"; - ep->supplies[1].supply = "vdd10"; - ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ep->supplies), - ep->supplies); - if (ret) - return ret; + if (pdata->res_ops && pdata->res_ops->init_regulator) { + ret = ep->pdata->res_ops->init_regulator(ep); + if (ret) + return ret; + } - ret = regulator_bulk_enable(ARRAY_SIZE(ep->supplies), ep->supplies); + ret = samsung_regulator_enable(ep); if (ret) return ret; platform_set_drvdata(pdev, ep); - - ret = exynos_add_pcie_port(ep, pdev); + ret = samsung_irq_init(ep, pdev); + if (ret) + goto fail_regulator; + ep->pci.pp.ops = pdata->host_ops; + ret = dw_pcie_host_init(&ep->pci.pp); if (ret < 0) - goto fail_probe; + goto fail_phy_init; return 0; -fail_probe: +fail_phy_init: phy_exit(ep->phy); - regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); +fail_regulator: + samsung_regulator_disable(ep); return ret; }
@@ -347,7 +401,7 @@ static void exynos_pcie_remove(struct platform_device *pdev) exynos_pcie_assert_core_reset(ep); phy_power_off(ep->phy); phy_exit(ep->phy); - regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); + samsung_regulator_disable(ep); } static int exynos_pcie_suspend_noirq(struct device *dev)
@@ -357,7 +411,7 @@ static int exynos_pcie_suspend_noirq(struct device *dev) exynos_pcie_assert_core_reset(ep); phy_power_off(ep->phy); phy_exit(ep->phy); - regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); + samsung_regulator_disable(ep); return 0; }
@@ -369,7 +423,7 @@ static int exynos_pcie_resume_noirq(struct device *dev) struct dw_pcie_rp *pp = &pci->pp; int ret; - ret = regulator_bulk_enable(ARRAY_SIZE(ep->supplies), ep->supplies); + ret = samsung_regulator_enable(ep); if (ret) return ret;
@@ -389,6 +443,7 @@ static const struct samsung_pcie_pdata exynos_5433_pcie_rc_pdata = { .dwc_ops = &exynos_dw_pcie_ops, .pci_ops = &exynos_pci_ops, .host_ops = &exynos_pcie_host_ops, + .res_ops = &exynos_res_ops_data, }; static const struct of_device_id exynos_pcie_of_match[] = {
--
2.49.0