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

Commit 291e9e3f authored by Even Xu's avatar Even Xu Committed by Jiri Kosina
Browse files

HID: intel-ish-hid: ipc: check FW status to distinguish ISH resume paths



For ISH resume, there are two paths, they need different way to handle: one
where ISH is not powered off, in that case a simple resume message is enough,
in other case we need a reset sequence.

We can use ISH FW status to distinguish those two cases and handle them
properly.

Signed-off-by: default avatarEven Xu <even.xu@intel.com>
Acked-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 5299a92a
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -110,6 +110,14 @@
#define IPC_ILUP_OFFS			(0)
#define IPC_ILUP_BIT			(1<<IPC_ILUP_OFFS)

/*
 * ISH FW status bits in ISH FW Status Register
 */
#define IPC_ISH_FWSTS_SHIFT		12
#define IPC_ISH_FWSTS_MASK		GENMASK(15, 12)
#define IPC_GET_ISH_FWSTS(status)	\
	(((status) & IPC_ISH_FWSTS_MASK) >> IPC_ISH_FWSTS_SHIFT)

/*
 * FW status bits (relevant)
 */
+12 −0
Original line number Diff line number Diff line
@@ -61,6 +61,18 @@ struct ish_hw {
	void __iomem *mem_addr;
};

/*
 * ISH FW status type
 */
enum {
	FWSTS_AFTER_RESET		= 0,
	FWSTS_WAIT_FOR_HOST		= 4,
	FWSTS_START_KERNEL_DMA		= 5,
	FWSTS_FW_IS_RUNNING		= 7,
	FWSTS_SENSOR_APP_LOADED		= 8,
	FWSTS_SENSOR_APP_RUNNING	= 15
};

#define to_ish_hw(dev) (struct ish_hw *)((dev)->hw)

irqreturn_t ish_irq_handler(int irq, void *dev_id);
+24 −10
Original line number Diff line number Diff line
@@ -206,12 +206,15 @@ static void ish_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
static struct device *ish_resume_device;

/* 50ms to get resume response */
#define WAIT_FOR_RESUME_ACK_MS		50

/**
 * ish_resume_handler() - Work function to complete resume
 * @work:	work struct
 *
 * The resume work function to complete resume function asynchronously.
 * There are two types of platforms, one where ISH is not powered off,
 * There are two resume paths, one where ISH is not powered off,
 * in that case a simple resume message is enough, others we need
 * a reset sequence.
 */
@@ -219,20 +222,31 @@ static void ish_resume_handler(struct work_struct *work)
{
	struct pci_dev *pdev = to_pci_dev(ish_resume_device);
	struct ishtp_device *dev = pci_get_drvdata(pdev);
	uint32_t fwsts;
	int ret;

	/* Get ISH FW status */
	fwsts = IPC_GET_ISH_FWSTS(dev->ops->get_fw_status(dev));

	/*
	 * If currently, in ISH FW, sensor app is loaded or beyond that,
	 * it means ISH isn't powered off, in this case, send a resume message.
	 */
	if (fwsts >= FWSTS_SENSOR_APP_LOADED) {
		ishtp_send_resume(dev);

	/* 50 ms to get resume response */
		/* Waiting to get resume response */
		if (dev->resume_flag)
			ret = wait_event_interruptible_timeout(dev->resume_wait,
				!dev->resume_flag,
						       msecs_to_jiffies(50));
				msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS));
	}

	/*
	 * If no resume response. This platform  is not S0ix compatible
	 * So on resume full reboot of ISH processor will happen, so
	 * need to go through init sequence again
	 * If in ISH FW, sensor app isn't loaded yet, or no resume response.
	 * That means this platform is not S0ix compatible, or something is
	 * wrong with ISH FW. So on resume, full reboot of ISH processor will
	 * happen, so need to go through init sequence again.
	 */
	if (dev->resume_flag)
		ish_init(dev);