diff mbox

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

Message ID 1486103093-2375-1-git-send-email-even.xu@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Xu, Even Feb. 3, 2017, 6:24 a.m. UTC
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: Even Xu <even.xu@intel.com>
---
 drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h |  8 +++++++
 drivers/hid/intel-ish-hid/ipc/hw-ish.h      | 12 ++++++++++
 drivers/hid/intel-ish-hid/ipc/pci-ish.c     | 34 ++++++++++++++++++++---------
 3 files changed, 44 insertions(+), 10 deletions(-)

Comments

Srinivas Pandruvada Feb. 7, 2017, 1:11 a.m. UTC | #1
On Fri, 2017-02-03 at 14:24 +0800, Even Xu wrote:
> 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: Even Xu <even.xu@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

Not an urgent fix and can be queued up for 4.11.

Thanks,
Srinivas

> ---
>  drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h |  8 +++++++
>  drivers/hid/intel-ish-hid/ipc/hw-ish.h      | 12 ++++++++++
>  drivers/hid/intel-ish-hid/ipc/pci-ish.c     | 34
> ++++++++++++++++++++---------
>  3 files changed, 44 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
> b/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
> index ab68afc..a5897b9 100644
> --- a/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
> +++ b/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
> @@ -111,6 +111,14 @@
>  #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)
>   */
>  #define	IPC_FWSTS_ILUP		0x1
> diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
> b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
> index d68cbcb..ddc8263 100644
> --- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
> +++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
> @@ -62,6 +62,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);
> diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> index 232c854..5b006f1 100644
> --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> @@ -205,12 +205,15 @@ static void ish_remove(struct pci_dev *pdev)
>  
>  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.
>   */
> @@ -218,20 +221,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;
>  
> -	ishtp_send_resume(dev);
> +	/* Get ISH FW status */
> +	fwsts = IPC_GET_ISH_FWSTS(dev->ops->get_fw_status(dev));
>  
> -	/* 50 ms to get resume response */
> -	if (dev->resume_flag)
> -		ret = wait_event_interruptible_timeout(dev-
> >resume_wait,
> -						       !dev-
> >resume_flag,
> -						       msecs_to_jiff
> ies(50));
> +	/*
> +	 * 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);
> +
> +		/* Waiting to get resume response */
> +		if (dev->resume_flag)
> +			ret = wait_event_interruptible_timeout(dev-
> >resume_wait,
> +				!dev->resume_flag,
> +				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);
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jiri Kosina Feb. 8, 2017, 3:13 a.m. UTC | #2
On Fri, 3 Feb 2017, Even Xu wrote:

> 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: Even Xu <even.xu@intel.com>

Applied to for-4.11/intel-ish. Thanks,
diff mbox

Patch

diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h b/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
index ab68afc..a5897b9 100644
--- a/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
@@ -111,6 +111,14 @@ 
 #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)
  */
 #define	IPC_FWSTS_ILUP		0x1
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
index d68cbcb..ddc8263 100644
--- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -62,6 +62,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);
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index 232c854..5b006f1 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -205,12 +205,15 @@  static void ish_remove(struct pci_dev *pdev)
 
 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.
  */
@@ -218,20 +221,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;
 
-	ishtp_send_resume(dev);
+	/* Get ISH FW status */
+	fwsts = IPC_GET_ISH_FWSTS(dev->ops->get_fw_status(dev));
 
-	/* 50 ms to get resume response */
-	if (dev->resume_flag)
-		ret = wait_event_interruptible_timeout(dev->resume_wait,
-						       !dev->resume_flag,
-						       msecs_to_jiffies(50));
+	/*
+	 * 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);
+
+		/* Waiting to get resume response */
+		if (dev->resume_flag)
+			ret = wait_event_interruptible_timeout(dev->resume_wait,
+				!dev->resume_flag,
+				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);