Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c232c0df authored by Kishon Vijay Abraham I's avatar Kishon Vijay Abraham I Committed by Lorenzo Pieralisi
Browse files

PCI: dwc: dra7xx: Enable x2 mode support for dra74x, dra76x and dra72x



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: default avatarKishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
parent 1c5d2cc7
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
@@ -81,6 +81,10 @@
#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");