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@samsung.com>
Signed-off-by: Shradha Todi <shradha.t@samsung.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
On Mon, May 19, 2025 at 01:01:47AM GMT, Shradha Todi wrote:
> +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);
No. Getting resources on every enable is making this much less readable.
NAK
Best regards,
Krzysztof
> -----Original Message-----
> From: Krzysztof Kozlowski <krzk@kernel.org>
> Sent: 21 May 2025 15:13
> To: Shradha Todi <shradha.t@samsung.com>
> Cc: linux-pci@vger.kernel.org; devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-samsung-soc@vger.kernel.or;
> linux-kernel@vger.kernel.org; linux-phy@lists.infradead.org; manivannan.sadhasivam@linaro.org; lpieralisi@kernel.org;
> kw@linux.com; robh@kernel.org; bhelgaas@google.com; jingoohan1@gmail.com; krzk+dt@kernel.org; conor+dt@kernel.org;
> alim.akhtar@samsung.com; vkoul@kernel.org; kishon@kernel.org; arnd@arndb.de; m.szyprowski@samsung.com;
> jh80.chung@samsung.com; Pankaj Dubey <pankaj.dubey@samsung.com>
> Subject: Re: [PATCH 05/10] PCI: exynos: Add structure to hold resource operations
>
> On Mon, May 19, 2025 at 01:01:47AM GMT, Shradha Todi wrote:
> > +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);
>
> No. Getting resources on every enable is making this much less readable.
>
> NAK
>
Will make sure that we get the resources only once during probe.
> Best regards,
> Krzysztof
© 2016 - 2025 Red Hat, Inc.