]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
PCI: dw-rockchip: Refactor the driver to prepare for EP mode
authorNiklas Cassel <cassel@kernel.org>
Fri, 7 Jun 2024 11:14:29 +0000 (13:14 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 9 Jul 2024 23:29:05 +0000 (18:29 -0500)
Refactor the driver to prepare for EP mode.

Add of-match data to the existing compatible, and explicitly define it as
DW_PCIE_RC_TYPE. This way, we will be able to add EP mode in a follow-up
commit in a much less intrusive way, which makes the follow-up commit much
easier to review.

No functional change intended.

Link: https://lore.kernel.org/linux-pci/20240607-rockchip-pcie-ep-v1-v5-9-0a042d6b0049@kernel.org
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Krzysztof WilczyƄski <kwilczynski@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/pci/controller/dwc/pcie-dw-rockchip.c

index 1380e3a5284ba55d96f6b354a1b8f3382f6e10f0..bd35620b1a96c078b0cc2d3aea07c630b0d07c90 100644 (file)
 #define PCIE_LTSSM_STATUS_MASK         GENMASK(5, 0)
 
 struct rockchip_pcie {
-       struct dw_pcie                  pci;
-       void __iomem                    *apb_base;
-       struct phy                      *phy;
-       struct clk_bulk_data            *clks;
-       unsigned int                    clk_cnt;
-       struct reset_control            *rst;
-       struct gpio_desc                *rst_gpio;
-       struct regulator                *vpcie3v3;
-       struct irq_domain               *irq_domain;
+       struct dw_pcie pci;
+       void __iomem *apb_base;
+       struct phy *phy;
+       struct clk_bulk_data *clks;
+       unsigned int clk_cnt;
+       struct reset_control *rst;
+       struct gpio_desc *rst_gpio;
+       struct regulator *vpcie3v3;
+       struct irq_domain *irq_domain;
+       const struct rockchip_pcie_of_data *data;
+};
+
+struct rockchip_pcie_of_data {
+       enum dw_pcie_device_mode mode;
 };
 
 static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, u32 reg)
@@ -195,7 +200,6 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
        struct device *dev = rockchip->pci.dev;
-       u32 val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE);
        int irq, ret;
 
        irq = of_irq_get_byname(dev->of_node, "legacy");
@@ -209,12 +213,6 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
        irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,
                                         rockchip);
 
-       /* LTSSM enable control mode */
-       rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
-
-       rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE,
-                                PCIE_CLIENT_GENERAL_CONTROL);
-
        return 0;
 }
 
@@ -294,13 +292,35 @@ static const struct dw_pcie_ops dw_pcie_ops = {
        .start_link = rockchip_pcie_start_link,
 };
 
+static int rockchip_pcie_configure_rc(struct rockchip_pcie *rockchip)
+{
+       struct dw_pcie_rp *pp;
+       u32 val;
+
+       /* LTSSM enable control mode */
+       val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE);
+       rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
+
+       rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE,
+                                PCIE_CLIENT_GENERAL_CONTROL);
+
+       pp = &rockchip->pci.pp;
+       pp->ops = &rockchip_pcie_host_ops;
+
+       return dw_pcie_host_init(pp);
+}
+
 static int rockchip_pcie_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct rockchip_pcie *rockchip;
-       struct dw_pcie_rp *pp;
+       const struct rockchip_pcie_of_data *data;
        int ret;
 
+       data = of_device_get_match_data(dev);
+       if (!data)
+               return -EINVAL;
+
        rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
        if (!rockchip)
                return -ENOMEM;
@@ -309,9 +329,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
 
        rockchip->pci.dev = dev;
        rockchip->pci.ops = &dw_pcie_ops;
-
-       pp = &rockchip->pci.pp;
-       pp->ops = &rockchip_pcie_host_ops;
+       rockchip->data = data;
 
        ret = rockchip_pcie_resource_get(pdev, rockchip);
        if (ret)
@@ -347,10 +365,21 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
        if (ret)
                goto deinit_phy;
 
-       ret = dw_pcie_host_init(pp);
-       if (!ret)
-               return 0;
+       switch (data->mode) {
+       case DW_PCIE_RC_TYPE:
+               ret = rockchip_pcie_configure_rc(rockchip);
+               if (ret)
+                       goto deinit_clk;
+               break;
+       default:
+               dev_err(dev, "INVALID device type %d\n", data->mode);
+               ret = -EINVAL;
+               goto deinit_clk;
+       }
+
+       return 0;
 
+deinit_clk:
        clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks);
 deinit_phy:
        rockchip_pcie_phy_deinit(rockchip);
@@ -361,8 +390,15 @@ disable_regulator:
        return ret;
 }
 
+static const struct rockchip_pcie_of_data rockchip_pcie_rc_of_data_rk3568 = {
+       .mode = DW_PCIE_RC_TYPE,
+};
+
 static const struct of_device_id rockchip_pcie_of_match[] = {
-       { .compatible = "rockchip,rk3568-pcie", },
+       {
+               .compatible = "rockchip,rk3568-pcie",
+               .data = &rockchip_pcie_rc_of_data_rk3568,
+       },
        {},
 };