Skip to content

Commit

Permalink
HID: intel-ish-hid: ipc: check FW status to distinguish ISH resume paths
Browse files Browse the repository at this point in the history
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>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Even Xu authored and Jiri Kosina committed Feb 8, 2017
1 parent 5299a92 commit 291e9e3
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
8 changes: 8 additions & 0 deletions drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
*/
Expand Down
12 changes: 12 additions & 0 deletions drivers/hid/intel-ish-hid/ipc/hw-ish.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
34 changes: 24 additions & 10 deletions drivers/hid/intel-ish-hid/ipc/pci-ish.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,33 +206,47 @@ 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.
*/
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);
Expand Down

0 comments on commit 291e9e3

Please sign in to comment.