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

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

Merge "msm: ep_pcie: Send pme from panic/reboot handler while in D3hot"

parents 79b770a9 9bc84cff
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -359,6 +359,7 @@ struct ep_pcie_dev_t {
	bool			     m2_autonomous;
	bool			     mhi_soc_reset_en;
	bool			     aoss_rst_clear;
	bool			     avoid_reboot_in_d3hot;
	u32                          dbi_base_reg;
	u32                          slv_space_reg;
	u32                          phy_status_reg;
+64 −0
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@
#include <linux/of_gpio.h>
#include <linux/clk/qcom.h>
#include <linux/reset.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/kdebug.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/interconnect.h>
@@ -3190,6 +3193,49 @@ int ep_pcie_core_config_db_routing(struct ep_pcie_db_config chdb_cfg,
	return 0;
}

static int ep_pcie_core_panic_reboot_callback(struct notifier_block *nb,
					   unsigned long reason, void *arg)
{
	struct ep_pcie_dev_t *dev = &ep_pcie_dev;
	u32 mhi_syserr = BIT(2)|(0xff << 8);
	unsigned long irqsave_flags;

	if (!ep_pcie_dev.avoid_reboot_in_d3hot)
		goto out;

	/* If the device is in D3hot state, bring it to D0 */
	spin_lock_irqsave(&dev->isr_lock, irqsave_flags);
	if (dev->l23_ready && atomic_read(&dev->perst_deast)) {

		EP_PCIE_INFO(dev,
			"PCIe V%d got %s notification while in D3hot\n",
			dev->rev, reason ? "reboot":"panic/die");

		/* Set MHI to SYSERR state */
		if (dev->config_mmio_init)
			ep_pcie_write_reg(dev->mmio, PCIE20_MHISTATUS,
						mhi_syserr);
		/* Bring device out of D3hot */
		ep_pcie_core_issue_inband_pme();
	}
	spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags);

out:
	return NOTIFY_DONE;
}

static struct notifier_block ep_pcie_core_reboot_notifier = {
	.notifier_call	= ep_pcie_core_panic_reboot_callback,
};

static struct notifier_block ep_pcie_core_die_notifier = {
	.notifier_call	= ep_pcie_core_panic_reboot_callback,
};

static struct notifier_block ep_pcie_core_panic_notifier = {
	.notifier_call	= ep_pcie_core_panic_reboot_callback,
};

struct ep_pcie_hw hw_drv = {
	.register_event	= ep_pcie_core_register_event,
	.deregister_event = ep_pcie_core_deregister_event,
@@ -3361,6 +3407,13 @@ static int ep_pcie_probe(struct platform_device *pdev)
		"PCIe V%d: MHI M2 autonomous is %s enabled\n",
		ep_pcie_dev.rev, ep_pcie_dev.m2_autonomous ? "" : "not");

	ep_pcie_dev.avoid_reboot_in_d3hot =
		of_property_read_bool((&pdev->dev)->of_node,
				"qcom,avoid-reboot-in-d3hot");
	EP_PCIE_DBG(&ep_pcie_dev,
	"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");

	ret = of_property_read_u32((&pdev->dev)->of_node,
				"qcom,mhi-soc-reset-offset",
				&ep_pcie_dev.mhi_soc_reset_offset);
@@ -3453,6 +3506,12 @@ static int ep_pcie_probe(struct platform_device *pdev)
	if (ret && !ep_pcie_debug_keep_resource)
		goto irq_deinit;

	register_reboot_notifier(&ep_pcie_core_reboot_notifier);
	/* Handler for wilful crash like BUG_ON */
	register_die_notifier(&ep_pcie_core_die_notifier);
	atomic_notifier_chain_register(&panic_notifier_list,
				       &ep_pcie_core_panic_notifier);

	qcom_edma_init(&pdev->dev);

	if (!ep_pcie_dev.perst_enum)
@@ -3476,6 +3535,11 @@ static int __exit ep_pcie_remove(struct platform_device *pdev)
{
	pr_debug("%s\n", __func__);

	unregister_reboot_notifier(&ep_pcie_core_reboot_notifier);
	unregister_die_notifier(&ep_pcie_core_die_notifier);
	atomic_notifier_chain_unregister(&panic_notifier_list,
					 &ep_pcie_core_panic_notifier);

	ep_pcie_irq_deinit(&ep_pcie_dev);
	ep_pcie_vreg_deinit(&ep_pcie_dev);
	ep_pcie_pipe_clk_deinit(&ep_pcie_dev);