]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
PCI: dwc: dra7xx: Enable x2 mode support for dra74x, dra76x and dra72x
authorKishon Vijay Abraham I <kishon@ti.com>
Thu, 24 Jan 2019 08:29:57 +0000 (13:59 +0530)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Thu, 31 Jan 2019 17:21:00 +0000 (17:21 +0000)
dra74x/dra76x and dra72x have separate compatible strings. Add support
for these compatible strings in pci-dra7xx driver to perform syscon
configurations required to get x2 mode working.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
drivers/pci/controller/dwc/pci-dra7xx.c

index a32d6dde7a579f6c21fe3daf79f10c566b48bb8d..5c72acb49c113529357b654d8a3303443320c5e2 100644 (file)
 #define MSI_REQ_GRANT                                  BIT(0)
 #define MSI_VECTOR_SHIFT                               7
 
+#define PCIE_1LANE_2LANE_SELECTION                     BIT(13)
+#define PCIE_B1C0_MODE_SEL                             BIT(2)
+#define PCIE_B0_B1_TSYNCEN                             BIT(0)
+
 struct dra7xx_pcie {
        struct dw_pcie          *pci;
        void __iomem            *base;          /* DT ti_conf */
@@ -93,6 +97,7 @@ struct dra7xx_pcie {
 
 struct dra7xx_pcie_of_data {
        enum dw_pcie_device_mode mode;
+       u32 b1co_mode_sel_mask;
 };
 
 #define to_dra7xx_pcie(x)      dev_get_drvdata((x)->dev)
@@ -529,6 +534,26 @@ static const struct dra7xx_pcie_of_data dra7xx_pcie_ep_of_data = {
        .mode = DW_PCIE_EP_TYPE,
 };
 
+static const struct dra7xx_pcie_of_data dra746_pcie_rc_of_data = {
+       .b1co_mode_sel_mask = BIT(2),
+       .mode = DW_PCIE_RC_TYPE,
+};
+
+static const struct dra7xx_pcie_of_data dra726_pcie_rc_of_data = {
+       .b1co_mode_sel_mask = GENMASK(3, 2),
+       .mode = DW_PCIE_RC_TYPE,
+};
+
+static const struct dra7xx_pcie_of_data dra746_pcie_ep_of_data = {
+       .b1co_mode_sel_mask = BIT(2),
+       .mode = DW_PCIE_EP_TYPE,
+};
+
+static const struct dra7xx_pcie_of_data dra726_pcie_ep_of_data = {
+       .b1co_mode_sel_mask = GENMASK(3, 2),
+       .mode = DW_PCIE_EP_TYPE,
+};
+
 static const struct of_device_id of_dra7xx_pcie_match[] = {
        {
                .compatible = "ti,dra7-pcie",
@@ -538,6 +563,22 @@ static const struct of_device_id of_dra7xx_pcie_match[] = {
                .compatible = "ti,dra7-pcie-ep",
                .data = &dra7xx_pcie_ep_of_data,
        },
+       {
+               .compatible = "ti,dra746-pcie-rc",
+               .data = &dra746_pcie_rc_of_data,
+       },
+       {
+               .compatible = "ti,dra726-pcie-rc",
+               .data = &dra726_pcie_rc_of_data,
+       },
+       {
+               .compatible = "ti,dra746-pcie-ep",
+               .data = &dra746_pcie_ep_of_data,
+       },
+       {
+               .compatible = "ti,dra726-pcie-ep",
+               .data = &dra726_pcie_ep_of_data,
+       },
        {},
 };
 
@@ -583,6 +624,34 @@ static int dra7xx_pcie_unaligned_memaccess(struct device *dev)
        return ret;
 }
 
+static int dra7xx_pcie_configure_two_lane(struct device *dev,
+                                         u32 b1co_mode_sel_mask)
+{
+       struct device_node *np = dev->of_node;
+       struct regmap *pcie_syscon;
+       unsigned int pcie_reg;
+       u32 mask;
+       u32 val;
+
+       pcie_syscon = syscon_regmap_lookup_by_phandle(np, "ti,syscon-lane-sel");
+       if (IS_ERR(pcie_syscon)) {
+               dev_err(dev, "unable to get ti,syscon-lane-sel\n");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32_index(np, "ti,syscon-lane-sel", 1,
+                                      &pcie_reg)) {
+               dev_err(dev, "couldn't get lane selection reg offset\n");
+               return -EINVAL;
+       }
+
+       mask = b1co_mode_sel_mask | PCIE_B0_B1_TSYNCEN;
+       val = PCIE_B1C0_MODE_SEL | PCIE_B0_B1_TSYNCEN;
+       regmap_update_bits(pcie_syscon, pcie_reg, mask, val);
+
+       return 0;
+}
+
 static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 {
        u32 reg;
@@ -603,6 +672,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
        const struct of_device_id *match;
        const struct dra7xx_pcie_of_data *data;
        enum dw_pcie_device_mode mode;
+       u32 b1co_mode_sel_mask;
 
        match = of_match_device(of_match_ptr(of_dra7xx_pcie_match), dev);
        if (!match)
@@ -610,6 +680,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 
        data = (struct dra7xx_pcie_of_data *)match->data;
        mode = (enum dw_pcie_device_mode)data->mode;
+       b1co_mode_sel_mask = data->b1co_mode_sel_mask;
 
        dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
        if (!dra7xx)
@@ -665,6 +736,12 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
        dra7xx->pci = pci;
        dra7xx->phy_count = phy_count;
 
+       if (phy_count == 2) {
+               ret = dra7xx_pcie_configure_two_lane(dev, b1co_mode_sel_mask);
+               if (ret < 0)
+                       dra7xx->phy_count = 1; /* Fallback to x1 lane mode */
+       }
+
        ret = dra7xx_pcie_enable_phy(dra7xx);
        if (ret) {
                dev_err(dev, "failed to enable phy\n");