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

Commit 69cec239 authored by Siddartha Mohanadoss's avatar Siddartha Mohanadoss
Browse files

msm: pcie_ep: Support inband wake for D3_HOT



Support waking up the host from D3_hot using inband PME
over PCIe for EP mode.

Change-Id: Ic6ed00e0f8d6d9ec3c83be922970d82c0b1b2a6c
Signed-off-by: default avatarSiddartha Mohanadoss <smohanad@codeaurora.org>
parent eb142de1
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
/* Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015, 2017-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -154,12 +154,13 @@ int ep_pcie_trigger_msi(struct ep_pcie_hw *phandle, u32 idx)
}
EXPORT_SYMBOL(ep_pcie_trigger_msi);

int ep_pcie_wakeup_host(struct ep_pcie_hw *phandle)
int ep_pcie_wakeup_host(struct ep_pcie_hw *phandle,
			enum ep_pcie_event event)
{
	if (WARN_ON(!phandle))
		return -EINVAL;

	return phandle->wakeup_host();
	return phandle->wakeup_host(event);
}
EXPORT_SYMBOL(ep_pcie_wakeup_host);

+29 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@

#define PCIE_MHI_STATUS(n)			((n) + 0x148)
#define TCSR_PERST_SEPARATION_ENABLE		0x270
#define PCIE_ISSUE_WAKE				1

/* debug mask sys interface */
static int ep_pcie_debug_mask;
@@ -2576,9 +2577,36 @@ int ep_pcie_core_trigger_msi(u32 idx)
	return EP_PCIE_ERROR;
}

int ep_pcie_core_wakeup_host(void)
static void ep_pcie_core_issue_inband_pme(void)
{
	struct ep_pcie_dev_t *dev = &ep_pcie_dev;
	unsigned long irqsave_flags;
	u32 pm_ctrl = 0;

	spin_lock_irqsave(&dev->isr_lock, irqsave_flags);

	EP_PCIE_DBG(dev,
		"PCIe V%d: request to assert inband wake\n",
		dev->rev);

	pm_ctrl = readl_relaxed(dev->parf + PCIE20_PARF_PM_CTRL);
	ep_pcie_write_reg(dev->parf, PCIE20_PARF_PM_CTRL,
						(pm_ctrl | BIT(4)));
	ep_pcie_write_reg(dev->parf, PCIE20_PARF_PM_CTRL, pm_ctrl);

	EP_PCIE_DBG(dev,
		"PCIe V%d: completed assert for inband wake\n",
		dev->rev);

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

static int ep_pcie_core_wakeup_host(enum ep_pcie_event event)
{
	struct ep_pcie_dev_t *dev = &ep_pcie_dev;

	if (event == EP_PCIE_EVENT_PM_D3_HOT)
		ep_pcie_core_issue_inband_pme();

	if (dev->perst_deast && !dev->l23_ready) {
		EP_PCIE_ERR(dev,
+2 −2
Original line number Diff line number Diff line
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -357,7 +357,7 @@ static ssize_t ep_pcie_cmd_debug(struct file *file,
		ep_pcie_config_outbound_iatu(phandle, entries, 2);
		break;
	case 13: /* wake up the host */
		ep_pcie_wakeup_host(phandle);
		ep_pcie_wakeup_host(phandle, EP_PCIE_EVENT_PM_D3_HOT);
		break;
	case 14: /* Configure routing of doorbells */
		ep_pcie_config_db_routing(phandle, chdb_cfg, erdb_cfg);
+11 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/debugfs.h>
#include <linux/ipa_mhi.h>
#include <linux/msm_ep_pcie.h>
#include "mhi_hwio.h"
#include "mhi_sm.h"
#include <linux/interrupt.h>
@@ -599,15 +600,22 @@ static int mhi_sm_change_to_M3(void)
static int mhi_sm_wakeup_host(enum mhi_dev_event event)
{
	int res = 0;
	enum ep_pcie_event pcie_event;

	MHI_SM_FUNC_ENTRY();

	if (mhi_sm_ctx->mhi_state == MHI_DEV_M3_STATE) {
		/*
		 * ep_pcie driver is responsible to send the right wakeup
		 * event, assert WAKE#, according to Link state
		 * Check and send D3_HOT to enable waking up the host
		 * using inband PME.
		 */
		res = ep_pcie_wakeup_host(mhi_sm_ctx->mhi_dev->phandle);
		if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_HOT_STATE)
			pcie_event = EP_PCIE_EVENT_PM_D3_HOT;
		else
			pcie_event = EP_PCIE_EVENT_PM_D3_COLD;

		res = ep_pcie_wakeup_host(mhi_sm_ctx->mhi_dev->phandle,
								pcie_event);
		if (res) {
			MHI_SM_ERR("Failed to wakeup MHI host, returned %d\n",
				res);
+3 −2
Original line number Diff line number Diff line
@@ -113,7 +113,7 @@ struct ep_pcie_hw {
				u32 num_entries);
	int (*get_msi_config)(struct ep_pcie_msi_config *cfg);
	int (*trigger_msi)(u32 idx);
	int (*wakeup_host)(void);
	int (*wakeup_host)(enum ep_pcie_event event);
	int (*enable_endpoint)(enum ep_pcie_options opt);
	int (*disable_endpoint)(void);
	int (*config_db_routing)(struct ep_pcie_db_config chdb_cfg,
@@ -231,12 +231,13 @@ int ep_pcie_trigger_msi(struct ep_pcie_hw *phandle, u32 idx);
/*
 * ep_pcie_wakeup_host - wake up the host.
 * @phandle:	PCIe endpoint HW driver handle
 * @event:	PCIe event of ep_pcie_event type
 *
 * This function asserts WAKE GPIO to wake up the host.
 *
 * Return: 0 on success, negative value on error
 */
int ep_pcie_wakeup_host(struct ep_pcie_hw *phandle);
int ep_pcie_wakeup_host(struct ep_pcie_hw *phandle, enum ep_pcie_event event);

/*
 * ep_pcie_enable_endpoint - enable PCIe endpoint.