]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: mediatek: Add support for Airoha AN7583 SoC
authorChristian Marangi <ansuelsmth@gmail.com>
Mon, 20 Oct 2025 11:11:09 +0000 (13:11 +0200)
committerManivannan Sadhasivam <mani@kernel.org>
Tue, 21 Oct 2025 01:59:56 +0000 (07:29 +0530)
Add support for the second PCIe Root Complex present on Airoha AN7583
SoC.

This is based on the Mediatek Gen1/2 PCIe driver and similar to Gen3
also require workaround for the reset signals.

Introduce a new quirk to skip having to reset signals and also introduce
some additional logic to configure the PBUS registers required for Airoha
SoC.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://patch.msgid.link/20251020111121.31779-6-ansuelsmth@gmail.com
drivers/pci/controller/pcie-mediatek.c

index 313da61a0b8aa57ee88cc2740aa3c200532f27fa..4b78b6528f9fd33138f021e816a0beb03e4dc558 100644 (file)
@@ -147,11 +147,13 @@ struct mtk_pcie_port;
  * @MTK_PCIE_FIX_CLASS_ID: host's class ID needed to be fixed
  * @MTK_PCIE_FIX_DEVICE_ID: host's device ID needed to be fixed
  * @MTK_PCIE_NO_MSI: Bridge has no MSI support, and relies on an external block
+ * @MTK_PCIE_SKIP_RSTB: Skip calling RSTB bits on PCIe probe
  */
 enum mtk_pcie_quirks {
        MTK_PCIE_FIX_CLASS_ID = BIT(0),
        MTK_PCIE_FIX_DEVICE_ID = BIT(1),
        MTK_PCIE_NO_MSI = BIT(2),
+       MTK_PCIE_SKIP_RSTB = BIT(3),
 };
 
 /**
@@ -687,23 +689,25 @@ static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
                regmap_update_bits(pcie->cfg, PCIE_SYS_CFG_V2, val, val);
        }
 
-       /* Assert all reset signals */
-       writel(0, port->base + PCIE_RST_CTRL);
+       if (!(soc->quirks & MTK_PCIE_SKIP_RSTB)) {
+               /* Assert all reset signals */
+               writel(0, port->base + PCIE_RST_CTRL);
 
-       /*
-        * Enable PCIe link down reset, if link status changed from link up to
-        * link down, this will reset MAC control registers and configuration
-        * space.
-        */
-       writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
+               /*
+                * Enable PCIe link down reset, if link status changed from
+                * link up to link down, this will reset MAC control registers
+                * and configuration space.
+                */
+               writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
 
-       msleep(PCIE_T_PVPERL_MS);
+               msleep(PCIE_T_PVPERL_MS);
 
-       /* De-assert PHY, PE, PIPE, MAC and configuration reset */
-       val = readl(port->base + PCIE_RST_CTRL);
-       val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
-              PCIE_MAC_SRSTB | PCIE_CRSTB;
-       writel(val, port->base + PCIE_RST_CTRL);
+               /* De-assert PHY, PE, PIPE, MAC and configuration reset */
+               val = readl(port->base + PCIE_RST_CTRL);
+               val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
+                      PCIE_MAC_SRSTB | PCIE_CRSTB;
+               writel(val, port->base + PCIE_RST_CTRL);
+       }
 
        /* Set up vendor ID and class code */
        if (soc->quirks & MTK_PCIE_FIX_CLASS_ID) {
@@ -824,6 +828,41 @@ static int mtk_pcie_startup_port(struct mtk_pcie_port *port)
        return 0;
 }
 
+static int mtk_pcie_startup_port_an7583(struct mtk_pcie_port *port)
+{
+       struct mtk_pcie *pcie = port->pcie;
+       struct device *dev = pcie->dev;
+       struct pci_host_bridge *host;
+       struct resource_entry *entry;
+       struct regmap *pbus_regmap;
+       resource_size_t addr;
+       u32 args[2], size;
+
+       /*
+        * Configure PBus base address and base address mask to allow
+        * the hw to detect if a given address is accessible on PCIe
+        * controller.
+        */
+       pbus_regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node,
+                                                          "mediatek,pbus-csr",
+                                                          ARRAY_SIZE(args),
+                                                          args);
+       if (IS_ERR(pbus_regmap))
+               return PTR_ERR(pbus_regmap);
+
+       host = pci_host_bridge_from_priv(pcie);
+       entry = resource_list_first_type(&host->windows, IORESOURCE_MEM);
+       if (!entry)
+               return -ENODEV;
+
+       addr = entry->res->start - entry->offset;
+       regmap_write(pbus_regmap, args[0], lower_32_bits(addr));
+       size = lower_32_bits(resource_size(entry->res));
+       regmap_write(pbus_regmap, args[1], GENMASK(31, __fls(size)));
+
+       return mtk_pcie_startup_port_v2(port);
+}
+
 static void mtk_pcie_enable_port(struct mtk_pcie_port *port)
 {
        struct mtk_pcie *pcie = port->pcie;
@@ -1208,6 +1247,13 @@ static const struct mtk_pcie_soc mtk_pcie_soc_mt7622 = {
        .quirks = MTK_PCIE_FIX_CLASS_ID,
 };
 
+static const struct mtk_pcie_soc mtk_pcie_soc_an7583 = {
+       .ops = &mtk_pcie_ops_v2,
+       .startup = mtk_pcie_startup_port_an7583,
+       .setup_irq = mtk_pcie_setup_irq,
+       .quirks = MTK_PCIE_FIX_CLASS_ID | MTK_PCIE_SKIP_RSTB,
+};
+
 static const struct mtk_pcie_soc mtk_pcie_soc_mt7629 = {
        .device_id = PCI_DEVICE_ID_MEDIATEK_7629,
        .ops = &mtk_pcie_ops_v2,
@@ -1217,6 +1263,7 @@ static const struct mtk_pcie_soc mtk_pcie_soc_mt7629 = {
 };
 
 static const struct of_device_id mtk_pcie_ids[] = {
+       { .compatible = "airoha,an7583-pcie", .data = &mtk_pcie_soc_an7583 },
        { .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
        { .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
        { .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_mt2712 },