[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250518193152.63476-6-shradha.t@samsung.com>
Date: Mon, 19 May 2025 01:01:47 +0530
From: Shradha Todi <shradha.t@...sung.com>
To: linux-pci@...r.kernel.org, devicetree@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org, linux-samsung-soc@...r.kernel.or,
linux-kernel@...r.kernel.org, linux-phy@...ts.infradead.org
Cc: manivannan.sadhasivam@...aro.org, lpieralisi@...nel.org, kw@...ux.com,
robh@...nel.org, bhelgaas@...gle.com, jingoohan1@...il.com,
krzk+dt@...nel.org, conor+dt@...nel.org, alim.akhtar@...sung.com,
vkoul@...nel.org, kishon@...nel.org, arnd@...db.de,
m.szyprowski@...sung.com, jh80.chung@...sung.com, Shradha Todi
<shradha.t@...sung.com>, Pankaj Dubey <pankaj.dubey@...sung.com>
Subject: [PATCH 05/10] PCI: exynos: Add structure to hold resource
operations
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 <pankaj.dubey@...sung.com>
Signed-off-by: Shradha Todi <shradha.t@...sung.com>
---
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
Powered by blists - more mailing lists