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

Commit df6a1cc6 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ep_pcie: support multiple link training options"

parents bb78141c 6eabaf89
Loading
Loading
Loading
Loading
+20 −15
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/msm_ep_pcie.h>

#define PCIE20_PARF_SYS_CTRL           0x00
#define PCIE20_PARF_DB_CTRL            0x10
#define PCIE20_PARF_PM_CTRL            0x20
#define PCIE20_PARF_PM_STTS            0x24
#define PCIE20_PARF_PHY_CTRL           0x40
@@ -41,6 +42,7 @@
#define PCIE20_PARF_AXI_MSTR_RD_HALT_NO_WRITES 0x1A4
#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT      0x1A8
#define PCIE20_PARF_Q2A_FLUSH          0x1AC
#define PCIE20_PARF_LTSSM              0x1B0
#define PCIE20_PARF_DEVICE_TYPE        0x1000

#define PCIE20_ELBI_VERSION            0x00
@@ -53,6 +55,7 @@
#define PCIE20_CLASS_CODE_REVISION_ID  0x08
#define PCIE20_BIST_HDR_TYPE           0x0C
#define PCIE20_BAR0                    0x10
#define PCIE20_SUBSYSTEM               0x2c
#define PCIE20_CAP_ID_NXT_PTR          0x40
#define PCIE20_CON_STATUS              0x44
#define PCIE20_MSI_CAP_ID_NEXT_CTRL    0x50
@@ -84,20 +87,20 @@
#define PCIE20_PLR_IATU_LTAR           0x918
#define PCIE20_PLR_IATU_UTAR           0x91c

#define PERST_TIMEOUT_US_MIN	              5000
#define PERST_TIMEOUT_US_MAX	              5100
#define PERST_CHECK_MAX_COUNT		      2000
#define LINK_UP_TIMEOUT_US_MIN	              5000
#define LINK_UP_TIMEOUT_US_MAX	              5100
#define LINK_UP_CHECK_MAX_COUNT		      2000
#define BME_TIMEOUT_US_MIN	              5000
#define BME_TIMEOUT_US_MAX	              5100
#define BME_CHECK_MAX_COUNT		      6000
#define PHY_STABILIZATION_DELAY_US_MIN	      995
#define PHY_STABILIZATION_DELAY_US_MAX	      1005
#define REFCLK_STABILIZATION_DELAY_US_MIN     995
#define REFCLK_STABILIZATION_DELAY_US_MAX     1005
#define PHY_READY_TIMEOUT_COUNT               10000
#define PERST_TIMEOUT_US_MIN	              1000
#define PERST_TIMEOUT_US_MAX	              1000
#define PERST_CHECK_MAX_COUNT		      30000
#define LINK_UP_TIMEOUT_US_MIN	              1000
#define LINK_UP_TIMEOUT_US_MAX	              1000
#define LINK_UP_CHECK_MAX_COUNT		      30000
#define BME_TIMEOUT_US_MIN	              1000
#define BME_TIMEOUT_US_MAX	              1000
#define BME_CHECK_MAX_COUNT		      30000
#define PHY_STABILIZATION_DELAY_US_MIN	      1000
#define PHY_STABILIZATION_DELAY_US_MAX	      1000
#define REFCLK_STABILIZATION_DELAY_US_MIN     1000
#define REFCLK_STABILIZATION_DELAY_US_MAX     1000
#define PHY_READY_TIMEOUT_COUNT               30000
#define XMLH_LINK_UP                          0x400

#define MAX_PROP_SIZE 32
@@ -107,7 +110,7 @@

#define EP_PCIE_LOG_PAGES 50
#define EP_PCIE_MAX_VREG 2
#define EP_PCIE_MAX_CLK 5
#define EP_PCIE_MAX_CLK 6
#define EP_PCIE_MAX_PIPE_CLK 1

#define EP_PCIE_ERROR -30655
@@ -283,6 +286,7 @@ struct ep_pcie_dev_t {
	bool                         perst_deast;
	bool                         power_on;
	bool                         suspending;
	bool                         l23_ready;
	bool                         l1ss_enabled;
	struct ep_pcie_msi_config    msi_cfg;

@@ -290,6 +294,7 @@ struct ep_pcie_dev_t {
};

extern struct ep_pcie_dev_t ep_pcie_dev;
extern struct ep_pcie_hw hw_drv;

static inline void ep_pcie_write_mask(void __iomem *addr,
				u32 clear_mask, u32 set_mask)
+42 −21
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@ module_param_named(debug_keep_resource, ep_pcie_debug_keep_resource,
struct ep_pcie_dev_t ep_pcie_dev = {0};

static struct ep_pcie_vreg_info_t ep_pcie_vreg_info[EP_PCIE_MAX_VREG] = {
	{NULL, "vreg-1.8", 1800000, 1800000, 1000, true},
	{NULL, "vreg-0.9", 1000000, 1000000, 24000, true}
	{NULL, "vreg-1.8", 1800000, 1800000, 14000, true},
	{NULL, "vreg-0.9", 1000000, 1000000, 40000, true}
};

static struct ep_pcie_gpio_info_t ep_pcie_gpio_info[EP_PCIE_MAX_GPIO] = {
@@ -66,7 +66,8 @@ static struct ep_pcie_clk_info_t
	{NULL, "pcie_0_mstr_axi_clk", 0, true},
	{NULL, "pcie_0_slv_axi_clk", 0, true},
	{NULL, "pcie_0_aux_clk", 1000000, true},
	{NULL, "pcie_0_ldo", 0, true}
	{NULL, "pcie_0_ldo", 0, true},
	{NULL, "pcie_0_phy_reset", 0, false}
};

static struct ep_pcie_clk_info_t
@@ -286,11 +287,10 @@ static int ep_pcie_clk_init(struct ep_pcie_dev_t *dev)
		info = &dev->clk[i];

		if (!info->hdl) {
			EP_PCIE_ERR(dev,
			EP_PCIE_DBG(dev,
				"PCIe V%d:  handle of Clock %s is NULL\n",
				dev->rev, info->name);
			rc = -EINVAL;
			break;
			continue;
		}

		if (info->freq) {
@@ -439,15 +439,17 @@ static void ep_pcie_bar_init(struct ep_pcie_dev_t *dev)
	/* Configure BAR mask via CS2 */
	ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, 0, BIT(0));
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0, mask);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0x4, 0);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0x8, mask);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0x10, mask);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0xc, 0);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0x10, 0);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0x14, 0);
	ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, BIT(0), 0);

	/* Configure BAR properties via CS */
	ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0, BIT(0));
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0, properties);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0x8, properties);
	ep_pcie_write_reg(dev->dm_core, PCIE20_BAR0 + 0x10, properties);
	ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0);
}

@@ -487,6 +489,9 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
	/* Disable the DBI Wakeup */
	ep_pcie_write_mask(dev->parf + PCIE20_PARF_SYS_CTRL, BIT(11), 0);

	/* Disable the debouncers */
	ep_pcie_write_reg(dev->parf, PCIE20_PARF_DB_CTRL, 0x73);

	/* Disable core clock CGC */
	ep_pcie_write_mask(dev->parf + PCIE20_PARF_SYS_CTRL, 0, BIT(6));

@@ -508,9 +513,12 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
	/* Set header type */
	ep_pcie_write_reg(dev->dm_core, PCIE20_BIST_HDR_TYPE, 0x10);

	/* Set Subsystem ID and Subsystem Vendor ID */
	ep_pcie_write_reg(dev->dm_core, PCIE20_SUBSYSTEM, 0xa01f17cb);

	/* Set the PMC Register - to support PME in D0, D3hot and D3cold */
	ep_pcie_write_mask(dev->dm_core + PCIE20_CAP_ID_NXT_PTR, 0,
						BIT(4)|BIT(3)|BIT(0));
						BIT(31)|BIT(30)|BIT(27));

	/* Set the Endpoint L0s Acceptable Latency to 1us (max) */
	ep_pcie_write_reg_field(dev->dm_core, PCIE20_DEVICE_CAPABILITIES,
@@ -528,8 +536,8 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
	ep_pcie_write_reg_field(dev->dm_core, PCIE20_LINK_CAPABILITIES,
		PCIE20_MASK_L0S_EXIT_LATENCY, 0x6);

	/* L1ss is not supported */
	ep_pcie_write_mask(dev->dm_core + PCIE20_L1SUB_CAPABILITY, 0x1f, 0);
	/* L1ss is supported */
	ep_pcie_write_mask(dev->dm_core + PCIE20_L1SUB_CAPABILITY, 0, 0x1f);

	/* Enable Clock Power Management */
	ep_pcie_write_reg_field(dev->dm_core, PCIE20_LINK_CAPABILITIES,
@@ -961,6 +969,8 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
				dev->rev);
			goto pipe_clk_fail;
		}

		dev->power_on = true;
	}

	if (!(opt & EP_PCIE_OPT_ENUM))
@@ -1026,7 +1036,7 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
		if (ep_pcie_phy_is_ready(dev))
			break;
		retries++;
		if (retries % 10 == 0)
		if (retries % 100 == 0)
			EP_PCIE_DBG(dev,
				"PCIe V%d: current number of PHY retries:%d.\n",
				dev->rev, retries);
@@ -1051,6 +1061,9 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
	ep_pcie_config_inbound_iatu(dev);

	/* enable link training */
	if (dev->phy_rev >= 3)
		ep_pcie_write_mask(dev->parf + PCIE20_PARF_LTSSM, 0, BIT(8));
	else
		ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_SYS_CTRL, 0, BIT(0));

	EP_PCIE_DBG(dev, "PCIe V%d: check if link is up\n", dev->rev);
@@ -1061,7 +1074,7 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
		usleep_range(LINK_UP_TIMEOUT_US_MIN, LINK_UP_TIMEOUT_US_MAX);
		val =  readl_relaxed(dev->elbi + PCIE20_ELBI_SYS_STTS);
		retries++;
		if (retries % 5 == 0)
		if (retries % 100 == 0)
			EP_PCIE_DBG(dev, "PCIe V%d: LTSSM_STATE:0x%x.\n",
					dev->rev, (val >> 0xC) & 0x3f);
	} while ((!(val & XMLH_LINK_UP) ||
@@ -1075,6 +1088,7 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
		goto link_fail;
	} else {
		dev->link_status = EP_PCIE_LINK_UP;
		dev->l23_ready = false;
		EP_PCIE_DBG(dev,
			"PCIe V%d: link is up after %d checkings (%d ms)\n",
			dev->rev, retries,
@@ -1112,11 +1126,11 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
		}
	}

	dev->power_on = true;
	dev->suspending = false;
	goto out;

link_fail:
	dev->power_on = false;
	if (!ep_pcie_debug_keep_resource)
		ep_pcie_pipe_clk_deinit(dev);
pipe_clk_fail:
@@ -1250,6 +1264,7 @@ static irqreturn_t ep_pcie_handle_dstate_change_irq(int irq, void *data)
		ep_pcie_reg_dump(dev, BIT(EP_PCIE_RES_DM_CORE), false);

	if (dstate == 3) {
		dev->l23_ready = true;
		dev->d3_counter++;
		EP_PCIE_DBG(dev,
			"PCIe V%d: No. %ld change to D3 state.\n",
@@ -1257,6 +1272,7 @@ static irqreturn_t ep_pcie_handle_dstate_change_irq(int irq, void *data)
		ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(1));
		ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_HOT);
	} else if (dstate == 0) {
		dev->l23_ready = false;
		dev->d0_counter++;
		EP_PCIE_DBG(dev,
			"PCIe V%d: No. %ld change to D0 state.\n",
@@ -1629,9 +1645,10 @@ int ep_pcie_core_trigger_msi(u32 idx)
	data = readl_relaxed(ep_pcie_dev.dm_core + PCIE20_MSI_DATA);

	if (addr && data) {
		ep_pcie_dev.msi_counter++;
		EP_PCIE_DUMP(&ep_pcie_dev,
			"PCIe V%d: No. %ld MSI fired for IRQ %d; index from client:%d\n",
			ep_pcie_dev.rev, ep_pcie_dev.msi_counter++,
			ep_pcie_dev.rev, ep_pcie_dev.msi_counter,
			data + idx, idx);
		ep_pcie_write_reg(ep_pcie_dev.msi, addr & 0xfff, data + idx);
		return 0;
@@ -1647,14 +1664,18 @@ int ep_pcie_core_wakeup_host(void)
{
	struct ep_pcie_dev_t *dev = &ep_pcie_dev;

	if (dev->perst_deast) {
	if (dev->perst_deast && !dev->l23_ready) {
		EP_PCIE_ERR(dev,
			"PCIe V%d: request to assert WAKE# when PERST is de-asserted.\n",
			"PCIe V%d: request to assert WAKE# when PERST is de-asserted and D3hot is not received.\n",
			dev->rev);
		return EP_PCIE_ERROR;
	} else {
		EP_PCIE_DBG(dev, "PCIe V%d: No. %ld to assert PCIe WAKE#.\n",
			dev->rev, ++dev->wake_counter);
		dev->wake_counter++;
		EP_PCIE_DBG(dev,
			"PCIe V%d: No. %ld to assert PCIe WAKE#; perst is %s de-asserted; D3hot is %s received.\n",
			dev->rev, dev->wake_counter,
			dev->perst_deast ? "" : "not",
			dev->l23_ready ? "" : "not");
		gpio_set_value(dev->gpio[EP_PCIE_GPIO_WAKE].num,
				1 - dev->gpio[EP_PCIE_GPIO_WAKE].on);
		gpio_set_value(dev->gpio[EP_PCIE_GPIO_WAKE].num,
@@ -1685,7 +1706,7 @@ int ep_pcie_core_config_db_routing(struct ep_pcie_db_config chdb_cfg,
	return 0;
}

static struct ep_pcie_hw hw_drv = {
struct ep_pcie_hw hw_drv = {
	.register_event	= ep_pcie_core_register_event,
	.deregister_event = ep_pcie_core_deregister_event,
	.get_linkstatus = ep_pcie_core_get_linkstatus,
+1 −5
Original line number Diff line number Diff line
@@ -296,7 +296,6 @@ static ssize_t ep_pcie_cmd_debug(struct file *file,
	unsigned int testcase = 0;
	struct ep_pcie_msi_config msi_cfg;
	int i;
	u32 device_id = 0;
	struct ep_pcie_hw *phandle = NULL;
	struct ep_pcie_iatu entries[2] = {
		{0x80000000, 0xbe7fffff, 0, 0},
@@ -305,10 +304,7 @@ static ssize_t ep_pcie_cmd_debug(struct file *file,
	struct ep_pcie_db_config chdb_cfg = {0x64, 0x6b, 0xfd4fa000};
	struct ep_pcie_db_config erdb_cfg = {0x64, 0x6b, 0xfd4fa080};

	if (dev->power_on) {
		device_id = readl_relaxed(dev->dm_core);
		phandle = ep_pcie_get_phandle(device_id);
	}
	phandle = ep_pcie_get_phandle(hw_drv.device_id);

	memset(str, 0, sizeof(str));
	ret = copy_from_user(str, buf, sizeof(str));