mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
Merge "msm: ep_pcie: Sending PME for device initiated D3cold exit"
This commit is contained in:
commit
9ef9b9d575
2 changed files with 88 additions and 0 deletions
|
|
@ -94,6 +94,8 @@
|
|||
#define PCIE20_SUBSYSTEM 0x2c
|
||||
#define PCIE20_CAP_ID_NXT_PTR 0x40
|
||||
#define PCIE20_CON_STATUS 0x44
|
||||
#define PCIE20_MASK_PME_EN BIT(8)
|
||||
#define PCIE20_MASK_PME_STATUS BIT(15)
|
||||
#define PCIE20_MSI_CAP_ID_NEXT_CTRL 0x50
|
||||
#define PCIE20_MSI_LOWER 0x54
|
||||
#define PCIE20_MSI_UPPER 0x58
|
||||
|
|
@ -360,6 +362,7 @@ struct ep_pcie_dev_t {
|
|||
bool mhi_soc_reset_en;
|
||||
bool aoss_rst_clear;
|
||||
bool avoid_reboot_in_d3hot;
|
||||
bool pme_in_wake_from_d3cold;
|
||||
u32 dbi_base_reg;
|
||||
u32 slv_space_reg;
|
||||
u32 phy_status_reg;
|
||||
|
|
@ -411,6 +414,8 @@ struct ep_pcie_dev_t {
|
|||
int perst_irq;
|
||||
atomic_t host_wake_pending;
|
||||
bool conf_ipa_msi_iatu;
|
||||
bool wake_from_d3cold;
|
||||
bool pme_en_d3;
|
||||
|
||||
struct ep_pcie_register_event *event_reg;
|
||||
struct work_struct handle_bme_work;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "ep_pcie_com.h"
|
||||
#include <asm/dma-iommu.h>
|
||||
|
|
@ -46,6 +47,9 @@
|
|||
#define ICC_AVG_BW 500
|
||||
#define ICC_PEAK_BW 800
|
||||
#define PERST_RAW_RESET_STATUS BIT(11)
|
||||
#define PCIE_PME_COUNT 2
|
||||
#define PCIE_PME_SLEEP_DELAY_US 10000
|
||||
#define PCIE_PME_RESEND_DELAY_US 100000
|
||||
|
||||
/* debug mask sys interface */
|
||||
static int ep_pcie_debug_mask;
|
||||
|
|
@ -120,6 +124,7 @@ static const struct ep_pcie_irq_info_t ep_pcie_irq_info[EP_PCIE_MAX_IRQ] = {
|
|||
};
|
||||
|
||||
static int ep_pcie_core_wakeup_host_internal(enum ep_pcie_event event);
|
||||
static void ep_pcie_core_issue_inband_pme(void);
|
||||
|
||||
int ep_pcie_get_debug_mask(void)
|
||||
{
|
||||
|
|
@ -790,6 +795,17 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
|
|||
ep_pcie_write_mask(dev->dm_core + PCIE20_CAP_ID_NXT_PTR, 0,
|
||||
BIT(31)|BIT(30)|BIT(27));
|
||||
|
||||
if (dev->pme_in_wake_from_d3cold && dev->pme_en_d3) {
|
||||
/*
|
||||
* PME_ENABLE is cleared after d3cold state if
|
||||
* retention flops are not present in the target.
|
||||
* Set PME_ENABLE, if it is seen as set during
|
||||
* d3hot to send PME message
|
||||
*/
|
||||
ep_pcie_write_mask(dev->dm_core + PCIE20_CON_STATUS, 0, PCIE20_MASK_PME_EN);
|
||||
dev->pme_en_d3 = false;
|
||||
}
|
||||
|
||||
/* Set the Endpoint L0s Acceptable Latency to 1us (max) */
|
||||
ep_pcie_write_reg_field(dev->dm_core,
|
||||
PCIE20_DEVICE_CAPABILITIES,
|
||||
|
|
@ -1675,6 +1691,46 @@ static void ep_pcie_core_toggle_wake_gpio(bool is_on)
|
|||
|
||||
}
|
||||
|
||||
static void ep_pcie_core_issue_pme_for_wake_from_d3cold(void)
|
||||
{
|
||||
struct ep_pcie_dev_t *dev = &ep_pcie_dev;
|
||||
u32 pme_count = 0, pme_reg;
|
||||
bool pme_en, pme_status;
|
||||
|
||||
pme_reg = readl_relaxed(dev->dm_core + PCIE20_CON_STATUS);
|
||||
pme_en = pme_reg & PCIE20_MASK_PME_EN;
|
||||
pme_status = pme_reg & PCIE20_MASK_PME_STATUS;
|
||||
|
||||
EP_PCIE_INFO(dev, "PCIe V%d: pme_reg: 0x%x, pme_en: %d, pme_status: %d\n",
|
||||
dev->rev, pme_reg, pme_en, pme_status);
|
||||
|
||||
if (pme_en) {
|
||||
do {
|
||||
/* Sending PME for device initiated d3_cold exit */
|
||||
ep_pcie_core_issue_inband_pme();
|
||||
/*Polling for pme_status to be 0 for 100ms*/
|
||||
readx_poll_timeout(readl_relaxed, dev->dm_core + PCIE20_CON_STATUS, pme_reg,
|
||||
!(pme_reg & PCIE20_MASK_PME_STATUS), PCIE_PME_SLEEP_DELAY_US,
|
||||
PCIE_PME_RESEND_DELAY_US);
|
||||
|
||||
pme_status = pme_reg & PCIE20_MASK_PME_STATUS;
|
||||
EP_PCIE_DBG(dev, "PCIe V%d: pme_status:%d\n", dev->rev, pme_status);
|
||||
|
||||
pme_count++;
|
||||
|
||||
if (!pme_status)
|
||||
break;
|
||||
|
||||
} while (pme_count < PCIE_PME_COUNT);
|
||||
|
||||
if (pme_status && pme_count == PCIE_PME_COUNT) {
|
||||
EP_PCIE_INFO(dev,
|
||||
"PCIe V%d: Host failed to acknowledge PME for device-initiated wake\n",
|
||||
dev->rev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -1951,6 +2007,16 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
|
|||
dev->rev);
|
||||
}
|
||||
|
||||
if (dev->pme_in_wake_from_d3cold && dev->wake_from_d3cold) {
|
||||
/*
|
||||
* Sending PME after link training for device
|
||||
* initiated D3cold to D0 transition, based on
|
||||
* PCIe specification
|
||||
*/
|
||||
ep_pcie_core_issue_pme_for_wake_from_d3cold();
|
||||
dev->wake_from_d3cold = false;
|
||||
}
|
||||
|
||||
checkbme:
|
||||
/* Clear AOSS_CC_RESET_STATUS::PERST_RAW_RESET_STATUS when linking up */
|
||||
if (dev->aoss_rst_clear)
|
||||
|
|
@ -2277,6 +2343,9 @@ static irqreturn_t ep_pcie_handle_dstate_change_irq(int irq, void *data)
|
|||
dev->rev, dev->d3_counter);
|
||||
ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(1));
|
||||
|
||||
dev->pme_en_d3 = readl_relaxed(dev->dm_core +
|
||||
PCIE20_CON_STATUS) & PCIE20_MASK_PME_EN;
|
||||
|
||||
if (dev->enumerated)
|
||||
ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_HOT);
|
||||
else
|
||||
|
|
@ -3147,6 +3216,13 @@ static int ep_pcie_core_wakeup_host_internal(enum ep_pcie_event event)
|
|||
if (!atomic_read(&dev->perst_deast)) {
|
||||
/*D3 cold handling*/
|
||||
ep_pcie_core_toggle_wake_gpio(true);
|
||||
if (dev->pme_in_wake_from_d3cold) {
|
||||
/*
|
||||
* Set below flag for device initiated
|
||||
* d3cold wake to send PME message
|
||||
*/
|
||||
dev->wake_from_d3cold = true;
|
||||
}
|
||||
} else if (dev->l23_ready) {
|
||||
EP_PCIE_ERR(dev,
|
||||
"PCIe V%d: request to assert WAKE# when in D3hot\n",
|
||||
|
|
@ -3423,6 +3499,13 @@ static int ep_pcie_probe(struct platform_device *pdev)
|
|||
"PCIe V%d: PME during reboot/panic (in D3hot) is %s needed\n",
|
||||
ep_pcie_dev.rev, ep_pcie_dev.avoid_reboot_in_d3hot ? "" : "not");
|
||||
|
||||
ep_pcie_dev.pme_in_wake_from_d3cold =
|
||||
of_property_read_bool((&pdev->dev)->of_node,
|
||||
"qcom,pme-in-wake-from-d3cold");
|
||||
EP_PCIE_DBG(&ep_pcie_dev,
|
||||
"PCIe V%d: PME is%s sent during wake from d3cold\n",
|
||||
ep_pcie_dev.rev, ep_pcie_dev.pme_in_wake_from_d3cold ? "" : " not");
|
||||
|
||||
ret = of_property_read_u32((&pdev->dev)->of_node,
|
||||
"qcom,mhi-soc-reset-offset",
|
||||
&ep_pcie_dev.mhi_soc_reset_offset);
|
||||
|
|
|
|||
Loading…
Reference in a new issue