]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: mediatek-gen3: Add Airoha EN7581 support
authorLorenzo Bianconi <lorenzo@kernel.org>
Wed, 3 Jul 2024 16:12:44 +0000 (18:12 +0200)
committerKrzysztof Wilczyński <kwilczynski@kernel.org>
Tue, 3 Sep 2024 13:37:41 +0000 (13:37 +0000)
Introduce support for Airoha EN7581 PCIe controller to mediatek-gen3
PCIe controller driver.

Link: https://lore.kernel.org/linux-pci/aca00bd672ee576ad96d279414fc0835ff31f637.1720022580.git.lorenzo@kernel.org
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
drivers/pci/controller/Kconfig
drivers/pci/controller/pcie-mediatek-gen3.c

index 4d2c188f58352775d62b0fe454f6900468e4bff0..9800b768105402d6dd1ba4b134c2ec23da6e4201 100644 (file)
@@ -196,7 +196,7 @@ config PCIE_MEDIATEK
 
 config PCIE_MEDIATEK_GEN3
        tristate "MediaTek Gen3 PCIe controller"
-       depends on ARCH_MEDIATEK || COMPILE_TEST
+       depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST
        depends on PCI_MSI
        help
          Adds support for PCIe Gen3 MAC controller for MediaTek SoCs.
index c325460d65a3a47ecf7a5d880834c707a650d5c4..5c19abac74e88129c8dcdbb3da8e568ebfaa11a9 100644 (file)
@@ -6,7 +6,9 @@
  * Author: Jianjun Wang <jianjun.wang@mediatek.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
 #include <linux/irq.h>
@@ -15,6 +17,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/msi.h>
+#include <linux/of_device.h>
+#include <linux/of_pci.h>
 #include <linux/pci.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #define PCI_CLASS(class)               (class << 8)
 #define PCIE_RC_MODE                   BIT(0)
 
+#define PCIE_EQ_PRESET_01_REG          0x100
+#define PCIE_VAL_LN0_DOWNSTREAM                GENMASK(6, 0)
+#define PCIE_VAL_LN0_UPSTREAM          GENMASK(14, 8)
+#define PCIE_VAL_LN1_DOWNSTREAM                GENMASK(22, 16)
+#define PCIE_VAL_LN1_UPSTREAM          GENMASK(30, 24)
+
 #define PCIE_CFGNUM_REG                        0x140
 #define PCIE_CFG_DEVFN(devfn)          ((devfn) & GENMASK(7, 0))
 #define PCIE_CFG_BUS(bus)              (((bus) << 8) & GENMASK(15, 8))
 #define PCIE_MSI_SET_ENABLE_REG                0x190
 #define PCIE_MSI_SET_ENABLE            GENMASK(PCIE_MSI_SET_NUM - 1, 0)
 
+#define PCIE_PIPE4_PIE8_REG            0x338
+#define PCIE_K_FINETUNE_MAX            GENMASK(5, 0)
+#define PCIE_K_FINETUNE_ERR            GENMASK(7, 6)
+#define PCIE_K_PRESET_TO_USE           GENMASK(18, 8)
+#define PCIE_K_PHYPARAM_QUERY          BIT(19)
+#define PCIE_K_QUERY_TIMEOUT           BIT(20)
+#define PCIE_K_PRESET_TO_USE_16G       GENMASK(31, 21)
+
 #define PCIE_MSI_SET_BASE_REG          0xc00
 #define PCIE_MSI_SET_OFFSET            0x10
 #define PCIE_MSI_SET_STATUS_OFFSET     0x04
 #define PCIE_ATR_TLP_TYPE_MEM          PCIE_ATR_TLP_TYPE(0)
 #define PCIE_ATR_TLP_TYPE_IO           PCIE_ATR_TLP_TYPE(2)
 
-#define MAX_NUM_PHY_RESETS             1
+#define MAX_NUM_PHY_RESETS             3
+
+/* Time in ms needed to complete PCIe reset on EN7581 SoC */
+#define PCIE_EN7581_RESET_TIME_MS      100
 
 struct mtk_gen3_pcie;
 
@@ -847,6 +868,85 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
        return 0;
 }
 
+static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
+{
+       struct device *dev = pcie->dev;
+       int err;
+       u32 val;
+
+       /*
+        * Wait for the time needed to complete the bulk assert in
+        * mtk_pcie_setup for EN7581 SoC.
+        */
+       mdelay(PCIE_EN7581_RESET_TIME_MS);
+
+       err = phy_init(pcie->phy);
+       if (err) {
+               dev_err(dev, "failed to initialize PHY\n");
+               return err;
+       }
+
+       err = phy_power_on(pcie->phy);
+       if (err) {
+               dev_err(dev, "failed to power on PHY\n");
+               goto err_phy_on;
+       }
+
+       err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
+       if (err) {
+               dev_err(dev, "failed to deassert PHYs\n");
+               goto err_phy_deassert;
+       }
+
+       /*
+        * Wait for the time needed to complete the bulk de-assert above.
+        * This time is specific for EN7581 SoC.
+        */
+       mdelay(PCIE_EN7581_RESET_TIME_MS);
+
+       pm_runtime_enable(dev);
+       pm_runtime_get_sync(dev);
+
+       err = clk_bulk_prepare(pcie->num_clks, pcie->clks);
+       if (err) {
+               dev_err(dev, "failed to prepare clock\n");
+               goto err_clk_prepare;
+       }
+
+       val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
+             FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
+             FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
+             FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41);
+       writel_relaxed(val, pcie->base + PCIE_EQ_PRESET_01_REG);
+
+       val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT |
+             FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) |
+             FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) |
+             FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
+       writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);
+
+       err = clk_bulk_enable(pcie->num_clks, pcie->clks);
+       if (err) {
+               dev_err(dev, "failed to prepare clock\n");
+               goto err_clk_enable;
+       }
+
+       return 0;
+
+err_clk_enable:
+       clk_bulk_unprepare(pcie->num_clks, pcie->clks);
+err_clk_prepare:
+       pm_runtime_put_sync(dev);
+       pm_runtime_disable(dev);
+       reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
+err_phy_deassert:
+       phy_power_off(pcie->phy);
+err_phy_on:
+       phy_exit(pcie->phy);
+
+       return err;
+}
+
 static int mtk_pcie_power_up(struct mtk_gen3_pcie *pcie)
 {
        struct device *dev = pcie->dev;
@@ -1113,7 +1213,18 @@ static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
        },
 };
 
+static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = {
+       .power_up = mtk_pcie_en7581_power_up,
+       .phy_resets = {
+               .id[0] = "phy-lane0",
+               .id[1] = "phy-lane1",
+               .id[2] = "phy-lane2",
+               .num_resets = 3,
+       },
+};
+
 static const struct of_device_id mtk_pcie_of_match[] = {
+       { .compatible = "airoha,en7581-pcie", .data = &mtk_pcie_soc_en7581 },
        { .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
        {},
 };