lkml.org 
[lkml]   [2013]   [Jul]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v1 3/3] ipc: Add support for default interrupt mode
    Date
    Added intel scu ipc access mode config option.

    Also, This patch adds support to enable ipc command interrupt
    mode by default. This functionality is enabled by following
    config option.

    CONFIG_INTEL_SCU_IPC_INTR_MODE=y

    Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
    ---
    drivers/platform/x86/Kconfig | 15 ++++++++++
    drivers/platform/x86/intel_scu_ipc.c | 53 ++++++++++++++++++++++++++++++++--
    2 files changed, 65 insertions(+), 3 deletions(-)

    diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
    index 36a9e60..26921ce 100644
    --- a/drivers/platform/x86/Kconfig
    +++ b/drivers/platform/x86/Kconfig
    @@ -654,6 +654,21 @@ config INTEL_SCU_IPC
    some embedded Intel x86 platforms. This is not needed for PC-type
    machines.

    +choice
    + prompt "IPC access mode"
    + depends on INTEL_SCU_IPC
    + default INTEL_SCU_IPC_INTR_MODE
    + ---help---
    + Select the desired access mode for IPC call.
    +
    +config INTEL_SCU_IPC_INTR_MODE
    + bool "Intel SCU IPC interrupt mode"
    +
    +config INTEL_SCU_IPC_POLL_MODE
    + bool "Intel SCU IPC polling mode"
    +
    +endchoice
    +
    config INTEL_SCU_IPC_UTIL
    tristate "Intel SCU IPC utility driver"
    depends on INTEL_SCU_IPC
    diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
    index aaaf1c1..6683ee0 100644
    --- a/drivers/platform/x86/intel_scu_ipc.c
    +++ b/drivers/platform/x86/intel_scu_ipc.c
    @@ -60,6 +60,7 @@

    #define IPC_WWBUF_SIZE 20 /* IPC Write buffer Size */
    #define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */
    +#define IPC_IOC 0x100 /* IPC command register IOC bit */

    enum {
    SCU_IPC_LINCROFT,
    @@ -110,6 +111,9 @@ struct intel_scu_ipc_dev {
    struct pci_dev *pdev;
    void __iomem *ipc_base;
    void __iomem *i2c_base;
    +#ifdef CONFIG_INTEL_SCU_IPC_INTR_MODE
    + struct completion cmd_complete;
    +#endif
    };

    static struct intel_scu_ipc_dev ipcdev; /* Only one for now */
    @@ -136,7 +140,12 @@ static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
    */
    static inline void ipc_command(u32 cmd) /* Send ipc command */
    {
    +#ifdef CONFIG_INTEL_SCU_IPC_INTR_MODE
    + INIT_COMPLETION(ipcdev.cmd_complete);
    + writel(cmd | IPC_IOC, ipcdev.ipc_base);
    +#else
    writel(cmd, ipcdev.ipc_base);
    +#endif
    }

    /*
    @@ -194,6 +203,37 @@ static inline int busy_loop(void) /* Wait till scu status is busy */
    return 0;
    }

    +#ifdef CONFIG_INTEL_SCU_IPC_INTR_MODE
    +/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */
    +static inline int ipc_wait_for_interrupt(void)
    +{
    + int status;
    + int ret = 0;
    +
    + if (!wait_for_completion_timeout(&ipcdev.cmd_complete, 3 * HZ)) {
    + ret = -ETIMEDOUT;
    + goto end;
    + }
    +
    + status = ipc_read_status();
    +
    + if ((status >> 1) & 1)
    + ret = -EIO;
    +
    +end:
    + return ret;
    +}
    +#endif
    +
    +int intel_scu_ipc_check_status(void)
    +{
    +#ifdef CONFIG_INTEL_SCU_IPC_INTR_MODE
    + return ipc_wait_for_interrupt();
    +#else
    + return busy_loop();
    +#endif
    +}
    +
    /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */
    static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
    {
    @@ -234,7 +274,7 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
    ipc_command(4 << 16 | id << 12 | 0 << 8 | op);
    }

    - err = busy_loop();
    + err = intel_scu_ipc_check_status();
    if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */
    /* Workaround: values are read as 0 without memcpy_fromio */
    memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16);
    @@ -429,7 +469,7 @@ int intel_scu_ipc_simple_command(int cmd, int sub)
    return -ENODEV;
    }
    ipc_command(sub << 12 | cmd);
    - err = busy_loop();
    + err = intel_scu_ipc_check_status();
    mutex_unlock(&ipclock);
    return err;
    }
    @@ -463,7 +503,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
    ipc_data_writel(*in++, 4 * i);

    ipc_command((inlen << 16) | (sub << 12) | cmd);
    - err = busy_loop();
    + err = intel_scu_ipc_check_status();

    for (i = 0; i < outlen; i++)
    *out++ = ipc_data_readl(4 * i);
    @@ -529,6 +569,9 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);
    */
    static irqreturn_t ioc(int irq, void *dev_id)
    {
    +#ifdef CONFIG_INTEL_SCU_IPC_INTR_MODE
    + complete(&ipcdev.cmd_complete);
    +#endif
    return IRQ_HANDLED;
    }

    @@ -566,6 +609,10 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
    if (!pci_resource)
    return -ENOMEM;

    +#ifdef CONFIG_INTEL_SCU_IPC_INTR_MODE
    + init_completion(&ipcdev.cmd_complete);
    +#endif
    +
    if (request_irq(dev->irq, ioc, 0, "intel_scu_ipc", &ipcdev))
    return -EBUSY;

    --
    1.7.9.5


    \
     
     \ /
      Last update: 2013-07-23 05:21    [W:3.341 / U:0.156 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site