Commit 1276ad01 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/controller/mediatek'

- Use clk_bulk_prepare_enable() instead of separate clk_bulk_prepare() and
  clk_bulk_enable() (Lorenzo Bianconi)

- Rearrange reset assert/deassert so they're both done in the *_power_up()
  callbacks (Lorenzo Bianconi)

- Document that Airoha EN7581 requires PHY init and power-on before PHY
  reset deassert, unlike other MediaTek Gen3 controllers (Lorenzo Bianconi)

- Move Airoha EN7581 post-reset delay from the en7581 clock .enable()
  method to mtk_pcie_en7581_power_up() (Lorenzo Bianconi)

- Sleep instead of delay during Airoha EN7581 power-up, since this is a
  non-atomic context (Lorenzo Bianconi)

- Skip PERST# assertion on Airoha EN7581 during probe and suspend/resume to
  avoid a hardware defect (Lorenzo Bianconi)

- Enable async probe to reduce system startup time (Douglas Anderson)

* pci/controller/mediatek:
  PCI: mediatek-gen3: Enable async probe by default
  PCI: mediatek-gen3: Avoid PCIe resetting via PERST# for Airoha EN7581 SoC
  PCI: mediatek-gen3: Rely on msleep() in mtk_pcie_en7581_power_up()
  PCI: mediatek-gen3: Move reset delay in mtk_pcie_en7581_power_up()
  PCI: mediatek-gen3: Add comment about initialization order in mtk_pcie_en7581_power_up()
  PCI: mediatek-gen3: Move reset/assert callbacks in .power_up()
  PCI: mediatek-gen3: Rely on clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up()
parents 09b7c162 17bd5e4d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -477,7 +477,6 @@ static int en7581_pci_enable(struct clk_hw *hw)
	       REG_PCI_CONTROL_PERSTOUT;
	val = readl(np_base + REG_PCI_CONTROL);
	writel(val | mask, np_base + REG_PCI_CONTROL);
	msleep(250);

	return 0;
}
+76 −41
Original line number Diff line number Diff line
@@ -125,6 +125,8 @@

#define MAX_NUM_PHY_RESETS		3

#define PCIE_MTK_RESET_TIME_US		10

/* Time in ms needed to complete PCIe reset on EN7581 SoC */
#define PCIE_EN7581_RESET_TIME_MS	100

@@ -133,10 +135,18 @@ struct mtk_gen3_pcie;
#define PCIE_CONF_LINK2_CTL_STS		(PCIE_CFG_OFFSET_ADDR + 0xb0)
#define PCIE_CONF_LINK2_LCR2_LINK_SPEED	GENMASK(3, 0)

enum mtk_gen3_pcie_flags {
	SKIP_PCIE_RSTB	= BIT(0), /* Skip PERST# assertion during device
				   * probing or suspend/resume phase to
				   * avoid hw bugs/issues.
				   */
};

/**
 * struct mtk_gen3_pcie_pdata - differentiate between host generations
 * @power_up: pcie power_up callback
 * @phy_resets: phy reset lines SoC data.
 * @flags: pcie device flags.
 */
struct mtk_gen3_pcie_pdata {
	int (*power_up)(struct mtk_gen3_pcie *pcie);
@@ -144,6 +154,7 @@ struct mtk_gen3_pcie_pdata {
		const char *id[MAX_NUM_PHY_RESETS];
		int num_resets;
	} phy_resets;
	u32 flags;
};

/**
@@ -438,22 +449,33 @@ static int mtk_pcie_startup_port(struct mtk_gen3_pcie *pcie)
	val |= PCIE_DISABLE_DVFSRC_VLT_REQ;
	writel_relaxed(val, pcie->base + PCIE_MISC_CTRL_REG);

	/*
	 * Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal
	 * causing occasional PCIe link down. In order to overcome the issue,
	 * PCIE_RSTB signals are not asserted/released at this stage and the
	 * PCIe block is reset using en7523_reset_assert() and
	 * en7581_pci_enable().
	 */
	if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
		/* Assert all reset signals */
		val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
	val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB;
		val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
		       PCIE_PE_RSTB;
		writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);

		/*
	 * Described in PCIe CEM specification sections 2.2 (PERST# Signal)
	 * and 2.2.1 (Initial Power-Up (G3 to S0)).
		 * Described in PCIe CEM specification revision 6.0.
		 *
		 * The deassertion of PERST# should be delayed 100ms (TPVPERL)
		 * for the power and clock to become stable.
		 */
	msleep(100);
		msleep(PCIE_T_PVPERL_MS);

		/* De-assert reset signals */
	val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB);
		val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
			 PCIE_PE_RSTB);
		writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
	}

	/* Check if the link is up or not */
	err = readl_poll_timeout(pcie->base + PCIE_LINK_STATUS_REG, val,
@@ -913,11 +935,20 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
	u32 val;

	/*
	 * Wait for the time needed to complete the bulk assert in
	 * mtk_pcie_setup for EN7581 SoC.
	 * The controller may have been left out of reset by the bootloader
	 * so make sure that we get a clean start by asserting resets here.
	 */
	mdelay(PCIE_EN7581_RESET_TIME_MS);
	reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
				  pcie->phy_resets);
	reset_control_assert(pcie->mac_reset);

	/* Wait for the time needed to complete the reset lines assert. */
	msleep(PCIE_EN7581_RESET_TIME_MS);

	/*
	 * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
	 * requires PHY initialization and power-on before PHY reset deassert.
	 */
	err = phy_init(pcie->phy);
	if (err) {
		dev_err(dev, "failed to initialize PHY\n");
@@ -940,17 +971,11 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
	 * Wait for the time needed to complete the bulk de-assert above.
	 * This time is specific for EN7581 SoC.
	 */
	mdelay(PCIE_EN7581_RESET_TIME_MS);
	msleep(PCIE_EN7581_RESET_TIME_MS);

	pm_runtime_enable(dev);
	pm_runtime_get_sync(dev);

	err = clk_bulk_prepare(pcie->num_clks, pcie->clks);
	if (err) {
		dev_err(dev, "failed to prepare clock\n");
		goto err_clk_prepare;
	}

	val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
	      FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
	      FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
@@ -963,17 +988,22 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
	      FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
	writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);

	err = clk_bulk_enable(pcie->num_clks, pcie->clks);
	err = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
	if (err) {
		dev_err(dev, "failed to prepare clock\n");
		goto err_clk_enable;
		goto err_clk_prepare_enable;
	}

	/*
	 * Airoha EN7581 performs PCIe reset via clk callbacks since it has a
	 * hw issue with PCIE_PE_RSTB signal. Add wait for the time needed to
	 * complete the PCIe reset.
	 */
	msleep(PCIE_T_PVPERL_MS);

	return 0;

err_clk_enable:
	clk_bulk_unprepare(pcie->num_clks, pcie->clks);
err_clk_prepare:
err_clk_prepare_enable:
	pm_runtime_put_sync(dev);
	pm_runtime_disable(dev);
	reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
@@ -990,6 +1020,15 @@ static int mtk_pcie_power_up(struct mtk_gen3_pcie *pcie)
	struct device *dev = pcie->dev;
	int err;

	/*
	 * The controller may have been left out of reset by the bootloader
	 * so make sure that we get a clean start by asserting resets here.
	 */
	reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
				  pcie->phy_resets);
	reset_control_assert(pcie->mac_reset);
	usleep_range(PCIE_MTK_RESET_TIME_US, 2 * PCIE_MTK_RESET_TIME_US);

	/* PHY power on and enable pipe clock */
	err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
	if (err) {
@@ -1074,14 +1113,6 @@ static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
	 * counter since the bulk is shared.
	 */
	reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
	/*
	 * The controller may have been left out of reset by the bootloader
	 * so make sure that we get a clean start by asserting resets here.
	 */
	reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);

	reset_control_assert(pcie->mac_reset);
	usleep_range(10, 20);

	/* Don't touch the hardware registers before power up */
	err = pcie->soc->power_up(pcie);
@@ -1231,10 +1262,12 @@ static int mtk_pcie_suspend_noirq(struct device *dev)
		return err;
	}

	/* Pull down the PERST# pin */
	if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
		/* Assert the PERST# pin */
		val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
		val |= PCIE_PE_RSTB;
		writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
	}

	dev_dbg(pcie->dev, "entered L2 states successfully");

@@ -1285,6 +1318,7 @@ static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = {
		.id[2] = "phy-lane2",
		.num_resets = 3,
	},
	.flags = SKIP_PCIE_RSTB,
};

static const struct of_device_id mtk_pcie_of_match[] = {
@@ -1301,6 +1335,7 @@ static struct platform_driver mtk_pcie_driver = {
		.name = "mtk-pcie-gen3",
		.of_match_table = mtk_pcie_of_match,
		.pm = &mtk_pcie_pm_ops,
		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
	},
};