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

Commit 9cea513d authored by Manikanta Maddireddy's avatar Manikanta Maddireddy Committed by Bjorn Helgaas
Browse files

PCI: tegra: Add Tegra186 PCIe support



Add Tegra186 PCIe support.  UPHY programming is performed by BPMP; PHY
enable calls are not required for Tegra186 PCIe.

Power partition ungate is done by BPMP powergate driver.  The Tegra186
DT description must include a "power-domains" property, which results in
dev->pm_domain being set.

Tested-by: default avatarMikko Perttunen <mperttunen@nvidia.com>
Tested-by: default avatarThierry Reding <treding@nvidia.com>
Signed-off-by: default avatarManikanta Maddireddy <mmaddireddy@nvidia.com>
[bhelgaas: add "power-domains" reference]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarMikko Perttunen <mperttunen@nvidia.com>
Acked-by: default avatarThierry Reding <treding@nvidia.com>
parent 904fb8e4
Loading
Loading
Loading
Loading
+109 −25
Original line number Diff line number Diff line
@@ -159,10 +159,13 @@
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE	(0x0 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420	(0x0 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1	(0x0 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_401	(0x0 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL	(0x1 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222	(0x1 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1	(0x1 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211	(0x1 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411	(0x2 << 20)
#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_111	(0x2 << 20)

#define AFI_FUSE			0x104
#define  AFI_FUSE_PCIE_T0_GEN2_DIS	(1 << 2)
@@ -252,6 +255,7 @@ struct tegra_pcie_soc {
	bool has_cml_clk;
	bool has_gen2;
	bool force_pca_enable;
	bool program_uphy;
};

static inline struct tegra_msi *to_tegra_msi(struct msi_controller *chip)
@@ -1032,11 +1036,13 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
		afi_writel(pcie, value, AFI_FUSE);
	}

	if (soc->program_uphy) {
		err = tegra_pcie_phy_power_on(pcie);
		if (err < 0) {
			dev_err(dev, "failed to power on PHY(s): %d\n", err);
			return err;
		}
	}

	/* take the PCIe interface module out of reset */
	reset_control_deassert(pcie->pcie_xrst);
@@ -1068,18 +1074,22 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
static void tegra_pcie_power_off(struct tegra_pcie *pcie)
{
	struct device *dev = pcie->dev;
	const struct tegra_pcie_soc *soc = pcie->soc;
	int err;

	/* TODO: disable and unprepare clocks? */

	if (soc->program_uphy) {
		err = tegra_pcie_phy_power_off(pcie);
		if (err < 0)
			dev_err(dev, "failed to power off PHY(s): %d\n", err);
	}

	reset_control_assert(pcie->pcie_xrst);
	reset_control_assert(pcie->afi_rst);
	reset_control_assert(pcie->pex_rst);

	if (!dev->pm_domain)
		tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);

	err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
@@ -1097,6 +1107,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
	reset_control_assert(pcie->afi_rst);
	reset_control_assert(pcie->pex_rst);

	if (!dev->pm_domain)
		tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);

	/* enable regulators */
@@ -1104,6 +1115,14 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
	if (err < 0)
		dev_err(dev, "failed to enable regulators: %d\n", err);

	if (dev->pm_domain) {
		err = clk_prepare_enable(pcie->pex_clk);
		if (err) {
			dev_err(dev, "failed to enable PEX clock: %d\n", err);
			return err;
		}
		reset_control_deassert(pcie->pex_rst);
	} else {
		err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
							pcie->pex_clk,
							pcie->pex_rst);
@@ -1111,6 +1130,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
			dev_err(dev, "powerup sequence failed: %d\n", err);
			return err;
		}
	}

	reset_control_deassert(pcie->afi_rst);

@@ -1282,6 +1302,7 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
	struct device *dev = pcie->dev;
	struct platform_device *pdev = to_platform_device(dev);
	struct resource *pads, *afi, *res;
	const struct tegra_pcie_soc *soc = pcie->soc;
	int err;

	err = tegra_pcie_clocks_get(pcie);
@@ -1296,11 +1317,13 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
		return err;
	}

	if (soc->program_uphy) {
		err = tegra_pcie_phys_get(pcie);
		if (err < 0) {
			dev_err(dev, "failed to get PHYs: %d\n", err);
			return err;
		}
	}

	err = tegra_pcie_power_on(pcie);
	if (err) {
@@ -1361,6 +1384,7 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
static int tegra_pcie_put_resources(struct tegra_pcie *pcie)
{
	struct device *dev = pcie->dev;
	const struct tegra_pcie_soc *soc = pcie->soc;
	int err;

	if (pcie->irq > 0)
@@ -1368,9 +1392,11 @@ static int tegra_pcie_put_resources(struct tegra_pcie *pcie)

	tegra_pcie_power_off(pcie);

	if (soc->program_uphy) {
		err = phy_exit(pcie->phy);
		if (err < 0)
			dev_err(dev, "failed to teardown PHY: %d\n", err);
	}

	return 0;
}
@@ -1636,7 +1662,31 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
	struct device *dev = pcie->dev;
	struct device_node *np = dev->of_node;

	if (of_device_is_compatible(np, "nvidia,tegra124-pcie") ||
	if (of_device_is_compatible(np, "nvidia,tegra186-pcie")) {
		switch (lanes) {
		case 0x010004:
			dev_info(dev, "4x1, 1x1 configuration\n");
			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_401;
			return 0;

		case 0x010102:
			dev_info(dev, "2x1, 1X1, 1x1 configuration\n");
			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211;
			return 0;

		case 0x010101:
			dev_info(dev, "1x1, 1x1, 1x1 configuration\n");
			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_111;
			return 0;

		default:
			dev_info(dev, "wrong configuration updated in DT, "
				 "switching to default 2x1, 1x1, 1x1 "
				 "configuration\n");
			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211;
			return 0;
		}
	} else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") ||
		   of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
		switch (lanes) {
		case 0x0000104:
@@ -1757,7 +1807,20 @@ static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
	struct device_node *np = dev->of_node;
	unsigned int i = 0;

	if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
	if (of_device_is_compatible(np, "nvidia,tegra186-pcie")) {
		pcie->num_supplies = 4;

		pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
					      sizeof(*pcie->supplies),
					      GFP_KERNEL);
		if (!pcie->supplies)
			return -ENOMEM;

		pcie->supplies[i++].supply = "dvdd-pex";
		pcie->supplies[i++].supply = "hvdd-pex-pll";
		pcie->supplies[i++].supply = "hvdd-pex";
		pcie->supplies[i++].supply = "vddio-pexctl-aud";
	} else if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
		pcie->num_supplies = 6;

		pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
@@ -2096,6 +2159,7 @@ static const struct tegra_pcie_soc tegra20_pcie = {
	.has_cml_clk = false,
	.has_gen2 = false,
	.force_pca_enable = false,
	.program_uphy = true,
};

static const struct tegra_pcie_soc tegra30_pcie = {
@@ -2111,6 +2175,7 @@ static const struct tegra_pcie_soc tegra30_pcie = {
	.has_cml_clk = true,
	.has_gen2 = false,
	.force_pca_enable = false,
	.program_uphy = true,
};

static const struct tegra_pcie_soc tegra124_pcie = {
@@ -2125,6 +2190,7 @@ static const struct tegra_pcie_soc tegra124_pcie = {
	.has_cml_clk = true,
	.has_gen2 = true,
	.force_pca_enable = false,
	.program_uphy = true,
};

static const struct tegra_pcie_soc tegra210_pcie = {
@@ -2139,9 +2205,27 @@ static const struct tegra_pcie_soc tegra210_pcie = {
	.has_cml_clk = true,
	.has_gen2 = true,
	.force_pca_enable = true,
	.program_uphy = true,
};

static const struct tegra_pcie_soc tegra186_pcie = {
	.num_ports = 3,
	.msi_base_shift = 8,
	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
	.pads_refclk_cfg0 = 0x80b880b8,
	.pads_refclk_cfg1 = 0x000480b8,
	.has_pex_clkreq_en = true,
	.has_pex_bias_ctrl = true,
	.has_intr_prsnt_sense = true,
	.has_cml_clk = false,
	.has_gen2 = true,
	.force_pca_enable = false,
	.program_uphy = false,
};

static const struct of_device_id tegra_pcie_of_match[] = {
	{ .compatible = "nvidia,tegra186-pcie", .data = &tegra186_pcie },
	{ .compatible = "nvidia,tegra210-pcie", .data = &tegra210_pcie },
	{ .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie },
	{ .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie },