platform/x86: intel_scu_ipc: Fix interrupt support
authorMika Westerberg <mika.westerberg@linux.intel.com>
Wed, 22 Jan 2020 16:28:04 +0000 (19:28 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2020 12:35:15 +0000 (04:35 -0800)
commit e48b72a568bbd641c91dad354138d3c17d03ee6f upstream.

Currently the driver has disabled interrupt support for Tangier but
actually interrupt works just fine if the command is not written twice
in a row. Also we need to ack the interrupt in the handler.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/platform/x86/intel_scu_ipc.c

index cdab916..e330ec7 100644 (file)
 struct intel_scu_ipc_pdata_t {
        u32 i2c_base;
        u32 i2c_len;
-       u8 irq_mode;
 };
 
 static const struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = {
        .i2c_base = 0xff12b000,
        .i2c_len = 0x10,
-       .irq_mode = 0,
 };
 
 /* Penwell and Cloverview */
 static const struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = {
        .i2c_base = 0xff12b000,
        .i2c_len = 0x10,
-       .irq_mode = 1,
 };
 
 static const struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {
        .i2c_base  = 0xff00d000,
        .i2c_len = 0x10,
-       .irq_mode = 0,
 };
 
 struct intel_scu_ipc_dev {
@@ -99,6 +95,9 @@ struct intel_scu_ipc_dev {
 
 static struct intel_scu_ipc_dev  ipcdev; /* Only one for now */
 
+#define IPC_STATUS             0x04
+#define IPC_STATUS_IRQ         BIT(2)
+
 /*
  * IPC Read Buffer (Read Only):
  * 16 byte buffer for receiving data from SCU, if IPC command
@@ -120,11 +119,8 @@ static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
  */
 static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)
 {
-       if (scu->irq_mode) {
-               reinit_completion(&scu->cmd_complete);
-               writel(cmd | IPC_IOC, scu->ipc_base);
-       }
-       writel(cmd, scu->ipc_base);
+       reinit_completion(&scu->cmd_complete);
+       writel(cmd | IPC_IOC, scu->ipc_base);
 }
 
 /*
@@ -610,9 +606,10 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);
 static irqreturn_t ioc(int irq, void *dev_id)
 {
        struct intel_scu_ipc_dev *scu = dev_id;
+       int status = ipc_read_status(scu);
 
-       if (scu->irq_mode)
-               complete(&scu->cmd_complete);
+       writel(status | IPC_STATUS_IRQ, scu->ipc_base + IPC_STATUS);
+       complete(&scu->cmd_complete);
 
        return IRQ_HANDLED;
 }
@@ -638,8 +635,6 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!pdata)
                return -ENODEV;
 
-       scu->irq_mode = pdata->irq_mode;
-
        err = pcim_enable_device(pdev);
        if (err)
                return err;