Commit f5c04da3 authored by Frank Li's avatar Frank Li Committed by Lorenzo Pieralisi
Browse files

PCI: imx6: Add iMX95 PCIe Root Complex support

parent 671a89c4
Loading
Loading
Loading
Loading
+71 −5
Original line number Diff line number Diff line
@@ -42,6 +42,19 @@
#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11, 8)
#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000

#define IMX95_PCIE_PHY_GEN_CTRL			0x0
#define IMX95_PCIE_REF_USE_PAD			BIT(17)

#define IMX95_PCIE_SS_RW_REG_0			0xf0
#define IMX95_PCIE_REF_CLKEN			BIT(23)
#define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)

#define IMX95_PE0_GEN_CTRL_1			0x1050
#define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0)

#define IMX95_PE0_GEN_CTRL_3			0x1058
#define IMX95_PCIE_LTSSM_EN			BIT(0)

#define to_imx6_pcie(x)	dev_get_drvdata((x)->dev)

enum imx6_pcie_variants {
@@ -52,6 +65,7 @@ enum imx6_pcie_variants {
	IMX8MQ,
	IMX8MM,
	IMX8MP,
	IMX95,
	IMX8MQ_EP,
	IMX8MM_EP,
	IMX8MP_EP,
@@ -63,6 +77,7 @@ enum imx6_pcie_variants {
#define IMX6_PCIE_FLAG_HAS_PHYDRV			BIT(3)
#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_check_flag(pci, val)     (pci->drvdata->flags & val)

@@ -179,6 +194,24 @@ static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)
	return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;
}

static int imx95_pcie_init_phy(struct imx6_pcie *imx6_pcie)
{
	regmap_update_bits(imx6_pcie->iomuxc_gpr,
			IMX95_PCIE_SS_RW_REG_0,
			IMX95_PCIE_PHY_CR_PARA_SEL,
			IMX95_PCIE_PHY_CR_PARA_SEL);

	regmap_update_bits(imx6_pcie->iomuxc_gpr,
			   IMX95_PCIE_PHY_GEN_CTRL,
			   IMX95_PCIE_REF_USE_PAD, 0);
	regmap_update_bits(imx6_pcie->iomuxc_gpr,
			   IMX95_PCIE_SS_RW_REG_0,
			   IMX95_PCIE_REF_CLKEN,
			   IMX95_PCIE_REF_CLKEN);

	return 0;
}

static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
{
	const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata;
@@ -575,6 +608,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
				   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
		break;
	case IMX7D:
	case IMX95:
		break;
	case IMX8MM:
	case IMX8MM_EP:
@@ -1279,12 +1313,32 @@ static int imx6_pcie_probe(struct platform_device *pdev)
		return PTR_ERR(imx6_pcie->turnoff_reset);
	}

	if (imx6_pcie->drvdata->gpr) {
	/* Grab GPR config register range */
		imx6_pcie->iomuxc_gpr =
			 syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr);
	if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
		dev_err(dev, "unable to find iomuxc registers\n");
		return PTR_ERR(imx6_pcie->iomuxc_gpr);
		if (IS_ERR(imx6_pcie->iomuxc_gpr))
			return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr),
					     "unable to find iomuxc registers\n");
	}

	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_SERDES)) {
		void __iomem *off = devm_platform_ioremap_resource_byname(pdev, "app");

		if (IS_ERR(off))
			return dev_err_probe(dev, PTR_ERR(off),
					     "unable to find serdes registers\n");

		static const struct regmap_config regmap_config = {
			.reg_bits = 32,
			.val_bits = 32,
			.reg_stride = 4,
		};

		imx6_pcie->iomuxc_gpr = devm_regmap_init_mmio(dev, off, &regmap_config);
		if (IS_ERR(imx6_pcie->iomuxc_gpr))
			return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr),
					     "unable to find iomuxc registers\n");
	}

	/* Grab PCIe PHY Tx Settings */
@@ -1457,6 +1511,17 @@ static const struct imx6_pcie_drvdata drvdata[] = {
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
	},
	[IMX95] = {
		.variant = IMX95,
		.flags = IMX6_PCIE_FLAG_HAS_SERDES,
		.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,
	},
	[IMX8MQ_EP] = {
		.variant = IMX8MQ_EP,
		.flags = IMX6_PCIE_FLAG_HAS_APP_RESET |
@@ -1501,6 +1566,7 @@ static const struct of_device_id imx6_pcie_of_match[] = {
	{ .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },
	{ .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },
	{ .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], },
	{ .compatible = "fsl,imx95-pcie", .data = &drvdata[IMX95], },
	{ .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], },