PCI: imx6: Add iMX95 Endpoint (EP) support
[linux-2.6-microblaze.git] / drivers / pci / controller / dwc / pci-imx6.c
index 1b2f40f..99a6027 100644 (file)
@@ -69,6 +69,7 @@ enum imx6_pcie_variants {
        IMX8MQ_EP,
        IMX8MM_EP,
        IMX8MP_EP,
+       IMX95_EP,
 };
 
 #define IMX6_PCIE_FLAG_IMX6_PHY                        BIT(0)
@@ -78,6 +79,7 @@ enum imx6_pcie_variants {
 #define IMX6_PCIE_FLAG_HAS_APP_RESET           BIT(4)
 #define IMX6_PCIE_FLAG_HAS_PHY_RESET           BIT(5)
 #define IMX6_PCIE_FLAG_HAS_SERDES              BIT(6)
+#define IMX6_PCIE_FLAG_SUPPORT_64BIT           BIT(7)
 
 #define imx6_check_flag(pci, val)     (pci->drvdata->flags & val)
 
@@ -610,6 +612,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
                break;
        case IMX7D:
        case IMX95:
+       case IMX95_EP:
                break;
        case IMX8MM:
        case IMX8MM_EP:
@@ -1044,6 +1047,23 @@ static const struct pci_epc_features imx8m_pcie_epc_features = {
        .align = SZ_64K,
 };
 
+/*
+ * BAR#        | Default BAR enable    | Default BAR Type      | Default BAR Size      | BAR Sizing Scheme
+ * ================================================================================================
+ * BAR0        | Enable                | 64-bit                | 1 MB                  | Programmable Size
+ * BAR1        | Disable               | 32-bit                | 64 KB                 | Fixed Size
+ *        BAR1 should be disabled if BAR0 is 64bit.
+ * BAR2        | Enable                | 32-bit                | 1 MB                  | Programmable Size
+ * BAR3        | Enable                | 32-bit                | 64 KB                 | Programmable Size
+ * BAR4        | Enable                | 32-bit                | 1M                    | Programmable Size
+ * BAR5        | Enable                | 32-bit                | 64 KB                 | Programmable Size
+ */
+static const struct pci_epc_features imx95_pcie_epc_features = {
+       .msi_capable = true,
+       .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_64K, },
+       .align = SZ_4K,
+};
+
 static const struct pci_epc_features*
 imx6_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -1086,6 +1106,18 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,
 
        pci->dbi_base2 = pci->dbi_base + pcie_dbi2_offset;
 
+       /*
+        * FIXME: Ideally, dbi2 base address should come from DT. But since only IMX95 is defining
+        * "dbi2" in DT, "dbi_base2" is set to NULL here for that platform alone so that the DWC
+        * core code can fetch that from DT. But once all platform DTs were fixed, this and the
+        * above "dbi_base2" setting should be removed.
+        */
+       if (device_property_match_string(dev, "reg-names", "dbi2") >= 0)
+               pci->dbi_base2 = NULL;
+
+       if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_SUPPORT_64BIT))
+               dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+
        ret = dw_pcie_ep_init(ep);
        if (ret) {
                dev_err(dev, "failed to initialize endpoint\n");
@@ -1556,6 +1588,20 @@ static const struct imx6_pcie_drvdata drvdata[] = {
                .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
                .epc_features = &imx8m_pcie_epc_features,
        },
+       [IMX95_EP] = {
+               .variant = IMX95_EP,
+               .flags = IMX6_PCIE_FLAG_HAS_SERDES |
+                        IMX6_PCIE_FLAG_SUPPORT_64BIT,
+               .clk_names = imx8mq_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mq_clks),
+               .ltssm_off = IMX95_PE0_GEN_CTRL_3,
+               .ltssm_mask = IMX95_PCIE_LTSSM_EN,
+               .mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
+               .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
+               .init_phy = imx95_pcie_init_phy,
+               .epc_features = &imx95_pcie_epc_features,
+               .mode = DW_PCIE_EP_TYPE,
+       },
 };
 
 static const struct of_device_id imx6_pcie_of_match[] = {
@@ -1570,6 +1616,7 @@ static const struct of_device_id imx6_pcie_of_match[] = {
        { .compatible = "fsl,imx8mq-pcie-ep", .data = &drvdata[IMX8MQ_EP], },
        { .compatible = "fsl,imx8mm-pcie-ep", .data = &drvdata[IMX8MM_EP], },
        { .compatible = "fsl,imx8mp-pcie-ep", .data = &drvdata[IMX8MP_EP], },
+       { .compatible = "fsl,imx95-pcie-ep", .data = &drvdata[IMX95_EP], },
        {},
 };