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

Commit d59603a2 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ep_pcie: Move tcsr perst delatch before link-up check"

parents f0b190bb 221fac37
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -4,7 +4,8 @@ Required properties:
  - compatible: should be "qcom,pcie-ep".
  - reg: should contain PCIe register maps.
  - reg-names: indicates various resources passed to driver by name.
		Should be "msi", "dm_core", "elbi", "parf", "phy", "mmio".
		Should be "msi", "dm_core", "elbi", "parf", "phy", "mmio",
		"tcsr_pcie_perst_en".
		These correspond to different modules within the PCIe domain.
  - #address-cells: Should provide a value of 0.
  - interrupt-parent: Should be the PCIe device node itself here.
@@ -78,8 +79,11 @@ Example:
			<0xbffff000 0x1000>,
			<0xfc520000 0x2000>,
			<0xfc526000 0x1000>,
			<0xfc527000 0x1000>;
		reg-names = "msi", "dm_core", "elbi", "parf", "phy", "mmio";
			<0xfc527000 0x1000>,
			<0x01fcb000 0x1000>;

		reg-names = "msi", "dm_core", "elbi", "parf", "phy", "mmio",
				"tcsr_pcie_perst";

		#address-cells = <0>;
		interrupt-parent = <&pcie_ep>;
+5 −0
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@
#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE_HI     0x35C
#define PCIE20_PARF_ATU_BASE_ADDR      0x634
#define PCIE20_PARF_ATU_BASE_ADDR_HI   0x638
#define PCIE20_PARF_BUS_DISCONNECT_CTRL          0x648
#define PCIE20_PARF_BUS_DISCONNECT_STATUS        0x64c

#define PCIE20_PARF_DEVICE_TYPE        0x1000
#define PCIE20_PARF_EDMA_BASE_ADDR      0x64C
#define PCIE20_PARF_EDMA_BASE_ADDR_HI   0x650
@@ -235,6 +238,7 @@ enum ep_pcie_res {
	EP_PCIE_RES_ELBI,
	EP_PCIE_RES_IATU,
	EP_PCIE_RES_EDMA,
	EP_PCIE_RES_TCSR_PERST,
	EP_PCIE_MAX_RES,
};

@@ -327,6 +331,7 @@ struct ep_pcie_dev_t {
	void __iomem                 *edma;
	void __iomem                 *elbi;
	void __iomem                 *iatu;
	void __iomem		     *tcsr_perst_en;

	struct msm_bus_scale_pdata   *bus_scale_table;
	u32                          bus_client;
+154 −59
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>

#define PCIE_MHI_STATUS(n)			((n) + 0x148)
/* debug mask sys interface */
static int ep_pcie_debug_mask;
static int ep_pcie_debug_keep_resource;
@@ -96,6 +97,7 @@ static const struct ep_pcie_res_info_t ep_pcie_res_info[EP_PCIE_MAX_RES] = {
	{"elbi",	NULL, NULL},
	{"iatu",	NULL, NULL},
	{"edma",	NULL, NULL},
	{"tcsr_pcie_perst_en",	NULL, NULL},
};

static const struct ep_pcie_irq_info_t ep_pcie_irq_info[EP_PCIE_MAX_IRQ] = {
@@ -138,6 +140,63 @@ static bool ep_pcie_confirm_linkup(struct ep_pcie_dev_t *dev,
	return true;
}

static int ep_pcie_reset_init(struct ep_pcie_dev_t *dev)
{
	int i, rc = 0;
	struct ep_pcie_reset_info_t *reset_info;

	for (i = 0; i < EP_PCIE_MAX_RESET; i++) {
		reset_info = &dev->reset[i];
		if (!reset_info->hdl)
			continue;

		rc = reset_control_assert(reset_info->hdl);
		if (rc) {
			if (!reset_info->required) {
				EP_PCIE_ERR(dev,
				"PCIe V%d: Optional reset: %s assert failed\n",
					dev->rev, reset_info->name);
				continue;
			} else {
				EP_PCIE_ERR(dev,
				"PCIe V%d: failed to assert reset for %s\n",
					dev->rev, reset_info->name);
				return rc;
			}
		} else {
			EP_PCIE_DBG(dev,
			"PCIe V%d: successfully asserted reset for %s\n",
				dev->rev, reset_info->name);
		}
		EP_PCIE_ERR(dev, "After Reset assert %s\n",
						reset_info->name);
		/* add a 1ms delay to ensure the reset is asserted */
		usleep_range(1000, 1005);

		rc = reset_control_deassert(reset_info->hdl);
		if (rc) {
			if (!reset_info->required) {
				EP_PCIE_ERR(dev,
				"PCIe V%d: Optional reset: %s deassert failed\n",
					dev->rev, reset_info->name);
				continue;
			} else {
				EP_PCIE_ERR(dev,
				"PCIe V%d: failed to deassert reset for %s\n",
					dev->rev, reset_info->name);
				return rc;
			}
		} else {
			EP_PCIE_DBG(dev,
			"PCIe V%d: successfully deasserted reset for %s\n",
				dev->rev, reset_info->name);
		}
		EP_PCIE_ERR(dev, "After Reset de-assert %s\n",
						reset_info->name);
	}
	return 0;
}

static int ep_pcie_gpio_init(struct ep_pcie_dev_t *dev)
{
	int i, rc = 0;
@@ -282,7 +341,6 @@ static int ep_pcie_clk_init(struct ep_pcie_dev_t *dev)
{
	int i, rc = 0;
	struct ep_pcie_clk_info_t *info;
	struct ep_pcie_reset_info_t *reset_info;

	EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);

@@ -354,34 +412,6 @@ static int ep_pcie_clk_init(struct ep_pcie_dev_t *dev)
		regulator_disable(dev->gdsc);
	}

	for (i = 0; i < EP_PCIE_MAX_RESET; i++) {
		reset_info = &dev->reset[i];
		if (reset_info->hdl) {
			rc = reset_control_assert(reset_info->hdl);
			if (rc)
				EP_PCIE_ERR(dev,
					"PCIe V%d: failed to assert reset for %s\n",
					dev->rev, reset_info->name);
			else
				EP_PCIE_DBG(dev,
					"PCIe V%d: successfully asserted reset for %s\n",
					dev->rev, reset_info->name);

			/* add a 1ms delay to ensure the reset is asserted */
			usleep_range(1000, 1005);

			rc = reset_control_deassert(reset_info->hdl);
			if (rc)
				EP_PCIE_ERR(dev,
					"PCIe V%d: failed to deassert reset for %s\n",
					dev->rev, reset_info->name);
			else
				EP_PCIE_DBG(dev,
					"PCIe V%d: successfully deasserted reset for %s\n",
					dev->rev, reset_info->name);
		}
	}

	return rc;
}

@@ -504,6 +534,9 @@ static void ep_pcie_bar_init(struct ep_pcie_dev_t *dev)

static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
{
	u32 mhi_status;
	void __iomem *mhi_status_addr;

	EP_PCIE_DBG(dev,
		"Initial version of MMIO is:0x%x\n",
		readl_relaxed(dev->mmio + PCIE20_MHIVER));
@@ -515,6 +548,15 @@ static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
		return;
	}

	mhi_status_addr = PCIE_MHI_STATUS(dev->mmio);
	mhi_status = readl_relaxed(mhi_status_addr);
	if (mhi_status & BIT(2)) {
		EP_PCIE_DBG(dev,
			"MHISYS error is set:%d, proceed to MHI\n",
			mhi_status);
		return;
	}

	ep_pcie_write_reg(dev->mmio, PCIE20_MHICFG, 0x02800880);
	ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
	ep_pcie_write_reg(dev->mmio, PCIE20_MHICTRL, 0x0);
@@ -529,11 +571,22 @@ static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)

static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
{
	uint32_t val = 0;

	EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);

	/* enable debug IRQ */
	ep_pcie_write_mask(dev->parf + PCIE20_PARF_DEBUG_INT_EN,
			0, BIT(3) | BIT(2) | BIT(1));
	/* Reconnect AXI master port */
	val = readl_relaxed(dev->parf + PCIE20_PARF_BUS_DISCONNECT_STATUS);
	if (val & BIT(0)) {
		EP_PCIE_DBG(dev,
		"PCIe V%d: AXI Master port was disconnected, reconnecting...\n",
			dev->rev);
		ep_pcie_write_mask(dev->parf + PCIE20_PARF_BUS_DISCONNECT_CTRL,
								0, BIT(0));
	}

	if (!configured) {
		/* Configure PCIe to endpoint mode */
@@ -761,7 +814,7 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
		ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, BIT(5), 0);
	}

	/* Configure MMIO */
	if (!configured)
		ep_pcie_config_mmio(dev);
}

@@ -1214,6 +1267,7 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,
	dev->edma = dev->res[EP_PCIE_RES_EDMA].base;
	dev->elbi = dev->res[EP_PCIE_RES_ELBI].base;
	dev->iatu = dev->res[EP_PCIE_RES_IATU].base;
	dev->tcsr_perst_en = dev->res[EP_PCIE_RES_TCSR_PERST].base;

out:
	kfree(clkfreq);
@@ -1243,6 +1297,11 @@ static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev)

	spin_lock_irqsave(&dev->isr_lock, irqsave_flags);

	if (dev->enumerated) {
		EP_PCIE_DBG(dev, "PCIe V%d: Enumeration already done\n",
				dev->rev);
		goto done;
	}
	dev->enumerated = true;
	dev->link_status = EP_PCIE_LINK_ENABLED;

@@ -1276,6 +1335,7 @@ static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev)
			"PCIe V%d: do not notify client about linkup\n",
			dev->rev);

done:
	spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags);
}

@@ -1329,20 +1389,30 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
		}

		dev->power_on = true;
	}

	if (!(opt & EP_PCIE_OPT_ENUM))
		goto out;
		 EP_PCIE_DBG(dev,
			 "TCSR PERST_EN value before configure:0x%x\n",
			 readl_relaxed(dev->tcsr_perst_en + 0x258));

		 /*
		  * Delatch PERST_EN with TCSR to avoid device reset
		  * during host reboot case.
		  */
		 writel_relaxed(0, dev->tcsr_perst_en + 0x258);

		 EP_PCIE_DBG(dev,
			 "TCSR PERST_EN value after configure:0x%x\n",
			 readl_relaxed(dev->tcsr_perst_en));

		 /* check link status during initial bootup */
		if (!dev->enumerated) {
			val = readl_relaxed(dev->parf + PCIE20_PARF_PM_STTS);
			val = val & PARF_XMLH_LINK_UP;
		EP_PCIE_DBG(dev, "PCIe V%d: Link status is 0x%x\n", dev->rev,
				val);
			EP_PCIE_DBG(dev, "PCIe V%d: Link status is 0x%x.\n",
					dev->rev, val);
			if (val) {
				EP_PCIE_INFO(dev,
				"PCIe V%d: link initialized by bootloader for LE PCIe endpoint; skip link training in HLOS\n",
					"PCIe V%d: link initialized by bootloader for LE PCIe endpoint; skip link training in HLOS.\n",
					dev->rev);
				ep_pcie_core_init(dev, true);
				dev->link_status = EP_PCIE_LINK_UP;
@@ -1354,18 +1424,40 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)

				if (ltssm_en) {
					EP_PCIE_ERR(dev,
					"PCIe V%d: link is not up when LTSSM has already enabled by bootloader\n",
						"PCIe V%d: link is not up when LTSSM has already enabled by bootloader.\n",
						dev->rev);
					ret = EP_PCIE_ERROR;
					goto link_fail;
				} else {
					EP_PCIE_DBG(dev,
					"PCIe V%d: Proceed with regular link training\n",
						"PCIe V%d: Proceed with regular link training.\n",
						dev->rev);
				}
			}
		}

		ret = ep_pcie_reset_init(dev);
		if (ret)
			goto link_fail;
	}

	if (!(opt & EP_PCIE_OPT_ENUM))
		goto out;

	EP_PCIE_DBG(dev,
		"TCSR PERST_EN value before configure:0x%x\n",
		readl_relaxed(dev->tcsr_perst_en + 0x258));

	/*
	 * Delatch PERST_EN with TCSR to avoid device reset
	 * during host reboot case.
	 */
	writel_relaxed(0, dev->tcsr_perst_en + 0x258);

	EP_PCIE_DBG(dev,
		"TCSR PERST_EN value after configure:0x%x\n",
		readl_relaxed(dev->tcsr_perst_en));

	if (opt & EP_PCIE_OPT_AST_WAKE) {
		/* assert PCIe WAKE# */
		EP_PCIE_INFO(dev, "PCIe V%d: assert PCIe WAKE#\n",
@@ -1417,6 +1509,9 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
		}
	}

	ret = ep_pcie_reset_init(dev);
	if (ret)
		goto link_fail;
	/* init PCIe PHY */
	ep_pcie_phy_init(dev);