Commit 86a3f3db authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/controller/rcar-gen4'

- Fix a typo that prevented correct PHY initialization (Marek Vasut)

- Add a missing 1ms delay after PWR reset assertion as required by the V4H
  manual (Marek Vasut)

- Assure reset has completed before DBI access to avoid SError (Marek
  Vasut)

- Fix inverted PHY initialization check, which sometimes led to timeouts
  and failure to start the controller (Marek Vasut)

* pci/controller/rcar-gen4:
  PCI: rcar-gen4: Fix inverted break condition in PHY initialization
  PCI: rcar-gen4: Assure reset occurs before DBI access
  PCI: rcar-gen4: Add missing 1ms delay after PWR reset assertion
  PCI: rcar-gen4: Fix PHY initialization
parents 531abff0 2bdf1d42
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -182,8 +182,17 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
		return ret;
	}

	if (!reset_control_status(dw->core_rsts[DW_PCIE_PWR_RST].rstc))
	if (!reset_control_status(dw->core_rsts[DW_PCIE_PWR_RST].rstc)) {
		reset_control_assert(dw->core_rsts[DW_PCIE_PWR_RST].rstc);
		/*
		 * R-Car V4H Reference Manual R19UH0186EJ0130 Rev.1.30 Apr.
		 * 21, 2025 page 585 Figure 9.3.2 Software Reset flow (B)
		 * indicates that for peripherals in HSC domain, after
		 * reset has been asserted by writing a matching reset bit
		 * into register SRCR, it is mandatory to wait 1ms.
		 */
		fsleep(1000);
	}

	val = readl(rcar->base + PCIEMSR0);
	if (rcar->drvdata->mode == DW_PCIE_RC_TYPE) {
@@ -204,6 +213,19 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
	if (ret)
		goto err_unprepare;

	/*
	 * Assure the reset is latched and the core is ready for DBI access.
	 * On R-Car V4H, the PCIe reset is asynchronous and does not take
	 * effect immediately, but needs a short time to complete. In case
	 * DBI access happens in that short time, that access generates an
	 * SError. To make sure that condition can never happen, read back the
	 * state of the reset, which should turn the asynchronous reset into
	 * synchronous one, and wait a little over 1ms to add additional
	 * safety margin.
	 */
	reset_control_status(dw->core_rsts[DW_PCIE_PWR_RST].rstc);
	fsleep(1000);

	if (rcar->drvdata->additional_common_init)
		rcar->drvdata->additional_common_init(rcar);

@@ -699,7 +721,7 @@ static int rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(23, 22), BIT(22));
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(18, 16), GENMASK(17, 16));
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(7, 6), BIT(6));
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(2, 0), GENMASK(11, 0));
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(2, 0), GENMASK(1, 0));
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x1d4, GENMASK(16, 15), GENMASK(16, 15));
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x514, BIT(26), BIT(26));
	rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x0f8, BIT(16), 0);
@@ -709,7 +731,7 @@ static int rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable
	val &= ~APP_HOLD_PHY_RST;
	writel(val, rcar->base + PCIERSTCTRL1);

	ret = readl_poll_timeout(rcar->phy_base + 0x0f8, val, !(val & BIT(18)), 100, 10000);
	ret = readl_poll_timeout(rcar->phy_base + 0x0f8, val, val & BIT(18), 100, 10000);
	if (ret < 0)
		return ret;