Message ID | 1438358336-79179-1-git-send-email-qipeng.zha@intel.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
On Fri, Jul 31, 2015 at 11:58:56PM +0800, Qipeng Zha wrote: > This driver provides support for Punit mailbox IPC on Intel platforms. > The heart of the Punit is the Foxton microcontroller and its firmware, > which provide mailbox interface for power management usage. > Mika, Andriy: I'm traveling over the next few days and could use some help ensuring this new driver receives some additional review. If you can, I'd appreciate your thoughts. > Signed-off-by: Qipeng Zha <qipeng.zha@intel.com> > --- > arch/x86/include/asm/intel_punit_ipc.h | 101 +++++++++ > drivers/platform/x86/Kconfig | 6 + > drivers/platform/x86/Makefile | 1 + > drivers/platform/x86/intel_punit_ipc.c | 388 +++++++++++++++++++++++++++++++++ > 4 files changed, 496 insertions(+) > create mode 100644 arch/x86/include/asm/intel_punit_ipc.h > create mode 100644 drivers/platform/x86/intel_punit_ipc.c > > diff --git a/arch/x86/include/asm/intel_punit_ipc.h b/arch/x86/include/asm/intel_punit_ipc.h > new file mode 100644 > index 0000000..08e3e14 > --- /dev/null > +++ b/arch/x86/include/asm/intel_punit_ipc.h > @@ -0,0 +1,101 @@ > +#ifndef _ASM_X86_INTEL_PUNIT_IPC_H_ > +#define _ASM_X86_INTEL_PUNIT_IPC_H_ > + > +/* Commands supported on GLM core, are handled by different bars, > + * unify these commands together here > + */ > +#define IPC_BIOS_PUNIT_CMD_BASE 0x00 > +#define IPC_GTD_PUNIT_CMD_BASE 0x20 > +#define IPC_ISPD_PUNIT_CMD_BASE 0x40 > + > +/* BIOS => Pcode commands */ > +#define IPC_BIOS_PUNIT_CMD_ZERO (IPC_BIOS_PUNIT_CMD_BASE + 0x00) > +#define IPC_BIOS_PUNIT_CMD_VR_INTERFACE (IPC_BIOS_PUNIT_CMD_BASE + 0x01) > +#define IPC_BIOS_PUNIT_CMD_READ_PCS (IPC_BIOS_PUNIT_CMD_BASE + 0x02) > +#define IPC_BIOS_PUNIT_CMD_WRITE_PCS (IPC_BIOS_PUNIT_CMD_BASE + 0x03) > +#define IPC_BIOS_PUNIT_CMD_READ_PCU_CONFIG (IPC_BIOS_PUNIT_CMD_BASE + 0x04) > +#define IPC_BIOS_PUNIT_CMD_WRITE_PCU_CONFIG (IPC_BIOS_PUNIT_CMD_BASE + 0x05) > +#define IPC_BIOS_PUNIT_CMD_READ_PL1_SETTING (IPC_BIOS_PUNIT_CMD_BASE + 0x06) > +#define IPC_BIOS_PUNIT_CMD_WRITE_PL1_SETTING (IPC_BIOS_PUNIT_CMD_BASE + 0x07) > +#define IPC_BIOS_PUNIT_CMD_TRIGGER_VDD_RAM (IPC_BIOS_PUNIT_CMD_BASE + 0x08) > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_INFO (IPC_BIOS_PUNIT_CMD_BASE + 0x09) > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_TRACE_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x0a) > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_TRACE_CTRL \ > + (IPC_BIOS_PUNIT_CMD_BASE + 0x0b) > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_EVENT_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x0c) > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_EVENT_CTRL \ > + (IPC_BIOS_PUNIT_CMD_BASE + 0x0d) > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_TRACE (IPC_BIOS_PUNIT_CMD_BASE + 0x0e) > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_TRACE (IPC_BIOS_PUNIT_CMD_BASE + 0x0f) > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_EVENT (IPC_BIOS_PUNIT_CMD_BASE + 0x10) > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_EVENT (IPC_BIOS_PUNIT_CMD_BASE + 0x11) > +#define IPC_BIOS_PUNIT_CMD_READ_MODULE_TEMP (IPC_BIOS_PUNIT_CMD_BASE + 0x12) > +#define IPC_BIOS_PUNIT_CMD_RESERVED (IPC_BIOS_PUNIT_CMD_BASE + 0x13) > +#define IPC_BIOS_PUNIT_CMD_READ_VOLTAGE_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x14) > +#define IPC_BIOS_PUNIT_CMD_WRITE_VOLTAGE_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x15) > +#define IPC_BIOS_PUNIT_CMD_READ_RATIO_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x16) > +#define IPC_BIOS_PUNIT_CMD_WRITE_RATIO_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x17) > +#define IPC_BIOS_PUNIT_CMD_READ_VF_GL_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x18) > +#define IPC_BIOS_PUNIT_CMD_WRITE_VF_GL_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x19) > +#define IPC_BIOS_PUNIT_CMD_READ_FM_SOC_TEMP_THRESH \ > + (IPC_BIOS_PUNIT_CMD_BASE + 0x1a) > +#define IPC_BIOS_PUNIT_CMD_WRITE_FM_SOC_TEMP_THRESH \ > + (IPC_BIOS_PUNIT_CMD_BASE + 0x1b) > + > +/*GT Driver => Pcode commands*/ > +#define IPC_GTD_PUNIT_CMD_ZERO (IPC_GTD_PUNIT_CMD_BASE + 0x00) > +#define IPC_GTD_PUNIT_CMD_CONFIG (IPC_GTD_PUNIT_CMD_BASE + 0x01) > +#define IPC_GTD_PUNIT_CMD_READ_ICCP_LIC_CDYN_SCAL \ > + (IPC_GTD_PUNIT_CMD_BASE + 0x02) > +#define IPC_GTD_PUNIT_CMD_WRITE_ICCP_LIC_CDYN_SCAL \ > + (IPC_GTD_PUNIT_CMD_BASE + 0x03) > +#define IPC_GTD_PUNIT_CMD_GET_WM_VAL (IPC_GTD_PUNIT_CMD_BASE + 0x06) > +#define IPC_GTD_PUNIT_CMD_WRITE_CONFIG_WISHREQ (IPC_GTD_PUNIT_CMD_BASE + 0x07) > +#define IPC_GTD_PUNIT_CMD_READ_REQ_DUTY_CYCLE (IPC_GTD_PUNIT_CMD_BASE + 0x16) > +#define IPC_GTD_PUNIT_CMD_DIS_VOL_FREQ_CHANGE_REQUEST \ > + (IPC_GTD_PUNIT_CMD_BASE + 0x17) > +#define IPC_GTD_PUNIT_CMD_DYNA_DUTY_CYCLE_CTRL (IPC_GTD_PUNIT_CMD_BASE + 0x1a) > +#define IPC_GTD_PUNIT_CMD_DYNA_DUTY_CYCLE_TUNING \ > + (IPC_GTD_PUNIT_CMD_BASE + 0x1c) > + > +/* ISP Driver => Pcode commands */ > +#define IPC_ISPD_PUNIT_CMD_ZERO (IPC_ISPD_PUNIT_CMD_BASE + 0x00) > +#define IPC_ISPD_PUNIT_CMD_CONFIG (IPC_ISPD_PUNIT_CMD_BASE + 0x01) > +#define IPC_ISPD_PUNIT_CMD_GET_ISP_LTR_VAL (IPC_ISPD_PUNIT_CMD_BASE + 0x02) > +#define IPC_ISPD_PUNIT_CMD_ACCESS_IU_FREQ_BOUNDS \ > + (IPC_ISPD_PUNIT_CMD_BASE + 0x03) > +#define IPC_ISPD_PUNIT_CMD_READ_CDYN_LEVEL (IPC_ISPD_PUNIT_CMD_BASE + 0x04) > +#define IPC_ISPD_PUNIT_CMD_WRITE_CDYN_LEVEL (IPC_ISPD_PUNIT_CMD_BASE + 0x05) > +#define IPC_ISPD_PUNIT_CMD_MAX (IPC_ISPD_PUNIT_CMD_BASE + 0x06) > + > +/* Error codes */ > +#define IPC_ERR_SUCCESS 0 > +#define IPC_ERR_INVALID_CMD 1 > +#define IPC_ERR_INVALID_PARAMETER 2 > +#define IPC_ERR_CMD_TIMEOUT 3 > +#define IPC_ERR_CMD_LOCKED 4 > +#define IPC_ERR_INVALID_VR_ID 5 > +#define IPC_ERR_VR_ERR 6 > + > +#if IS_ENABLED(CONFIG_INTEL_PUNIT_IPC) > + > +int intel_punit_ipc_simple_command(int cmd, int para1, int para2); > +int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out); > + > +#else > + > +static intline int intel_punit_ipc_simple_command(int cmd, > + int para1, int para2); > +{ > + return -EINVAL; > +} > + > +static inline int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, > + u32 *in, u32 *out); > +{ > + return -EINVAL; > +} > + > +#endif /*CONFIG_INTEL_PUNIT_IPC*/ > + > +#endif > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig > index 346f1fd..42ada9b 100644 > --- a/drivers/platform/x86/Kconfig > +++ b/drivers/platform/x86/Kconfig > @@ -891,4 +891,10 @@ config INTEL_PMC_IPC > The PMC is an ARC processor which defines IPC commands for communication > with other entities in the CPU. > > +config INTEL_PUNIT_IPC > + tristate "Intel PUNIT IPC Driver" > + default y > + ---help--- > + IPC is used to bridge the communications between kernel and PUNIT > + > endif # X86_PLATFORM_DEVICES > diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile > index 1051372..eea765f 100644 > --- a/drivers/platform/x86/Makefile > +++ b/drivers/platform/x86/Makefile > @@ -59,3 +59,4 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o > obj-$(CONFIG_PVPANIC) += pvpanic.o > obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o > obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o > +obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o > diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c > new file mode 100644 > index 0000000..78cb794 > --- /dev/null > +++ b/drivers/platform/x86/intel_punit_ipc.c > @@ -0,0 +1,388 @@ > +/* > + * intel_punit_ipc.c: Driver for the Intel Punit Mailbox IPC mechanism > + * > + * (C) Copyright 2015 Intel Corporation > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * The heart of the Punit is the Foxton microcontroller and its firmware, > + * which provide mailbox interface for power management usage. > + */ > + > +#include <linux/module.h> > +#include <linux/delay.h> > +#include <linux/errno.h> > +#include <linux/init.h> > +#include <linux/device.h> > +#include <linux/pm.h> > +#include <linux/acpi.h> > +#include <linux/interrupt.h> > +#include <linux/kernel.h> > +#include <linux/bitops.h> > +#include <linux/atomic.h> > +#include <linux/notifier.h> > +#include <linux/suspend.h> > +#include <linux/platform_device.h> > +#include <asm/intel_punit_ipc.h> > + > +/* Mailbox registers */ > +#define MAILBOX_DATA_LOW 0x0 > +#define MAILBOX_INTERFACE 0x4 > +#define CMD_RUN (1 << 31) > +#define CMD_ERRCODE_MASK 0xFF > +#define CMD_PARA1_SHIFT 8 > +#define CMD_PARA2_SHIFT 16 > +#define CMD_MASK 0xFF > +#define MAILBOX_DATA_HIGH 0x8 > + > +#define MAILBOX_REGISTER_SPACE 0x10 > + > +#define CMD_TIMEOUT_SECONDS 3 > + > +/* Three external mailbox */ > +enum mailbox_type { > + BIOS_MAILBOX, > + GTDRIVER_MAILBOX, > + ISPDRIVER_MAILBOX, > + RESERVED_MAILBOX, > +}; > + > +struct intel_punit_ipc_controller { > + struct platform_device *pdev; > + struct mutex lock; > + void __iomem *base[RESERVED_MAILBOX]; > + struct completion cmd_complete; > + int irq; > + > + int cmd; > + enum mailbox_type type; > +}; > + > +static char *ipc_err_sources[] = { > + [IPC_ERR_SUCCESS] = > + "no error", > + [IPC_ERR_INVALID_CMD] = > + "invalid command", > + [IPC_ERR_INVALID_PARAMETER] = > + "invalid parameter", > + [IPC_ERR_CMD_TIMEOUT] = > + "command timeout", > + [IPC_ERR_CMD_LOCKED] = > + "command locked", > + [IPC_ERR_INVALID_VR_ID] = > + "invalid vr id", > + [IPC_ERR_VR_ERR] = > + "vr error", > +}; > + > +static struct intel_punit_ipc_controller ipcdev; > + > +static inline u32 ipc_read_status(void) > +{ > + return readl(ipcdev.base[ipcdev.type] + MAILBOX_INTERFACE); > +} > + > +static inline void ipc_write_cmd(u32 cmd) > +{ > + writel(cmd, ipcdev.base[ipcdev.type] + MAILBOX_INTERFACE); > +} > + > +static inline u32 ipc_read_data_low(void) > +{ > + return readl(ipcdev.base[ipcdev.type] + MAILBOX_DATA_LOW); > +} > + > +static inline u32 ipc_read_data_high(void) > +{ > + return readl(ipcdev.base[ipcdev.type] + MAILBOX_DATA_HIGH); > +} > + > +static inline void ipc_write_data_low(u32 data) > +{ > + writel(data, ipcdev.base[ipcdev.type] + MAILBOX_DATA_LOW); > +} > + > +static inline void ipc_write_data_high(u32 data) > +{ > + writel(data, ipcdev.base[ipcdev.type] + MAILBOX_DATA_HIGH); > +} > + > +static int intel_punit_init_cmd(u32 cmd) > +{ > + cmd &= CMD_MASK; > + if (cmd < IPC_BIOS_PUNIT_CMD_BASE) > + return -EINVAL; > + else if (cmd < IPC_GTD_PUNIT_CMD_BASE) > + ipcdev.type = BIOS_MAILBOX; > + else if (cmd < IPC_ISPD_PUNIT_CMD_BASE) > + ipcdev.type = GTDRIVER_MAILBOX; > + else if (cmd < IPC_ISPD_PUNIT_CMD_MAX) > + ipcdev.type = ISPDRIVER_MAILBOX; > + else > + return -EINVAL; > + > + return 0; > +} > + > +static int intel_punit_ipc_send_command(u32 cmd) > +{ > + int ret; > + > + ret = intel_punit_init_cmd(cmd); > + if (ret) > + return ret; > + ipcdev.cmd = cmd; > + reinit_completion(&ipcdev.cmd_complete); > + ipc_write_cmd(cmd); > + return 0; > +} > + > +static int intel_punit_ipc_check_status(void) > +{ > + int loops = CMD_TIMEOUT_SECONDS * USEC_PER_SEC; > + int ret = 0; > + int status; > + int errcode; > + > + if (ipcdev.irq) { > + if (0 == wait_for_completion_timeout( > + &ipcdev.cmd_complete, > + CMD_TIMEOUT_SECONDS * HZ)) { > + dev_err(&ipcdev.pdev->dev, > + "IPC timed out, IPC_CMD=0x%x\n", ipcdev.cmd); > + return -ETIMEDOUT; > + } > + } else { > + while ((ipc_read_status() & CMD_RUN) && --loops) > + udelay(1); > + if (!loops) { > + dev_err(&ipcdev.pdev->dev, > + "IPC timed out, IPC_CMD=0x%x\n", ipcdev.cmd); > + return -ETIMEDOUT; > + } > + } > + > + status = ipc_read_status(); > + errcode = status & CMD_ERRCODE_MASK; > + if (errcode) { > + ret = -EIO; > + if (errcode < ARRAY_SIZE(ipc_err_sources)) > + dev_err(&ipcdev.pdev->dev, > + "IPC failed: %s, IPC_STS=0x%x, IPC_CMD=0x%x\n", > + ipc_err_sources[errcode], status, ipcdev.cmd); > + else > + dev_err(&ipcdev.pdev->dev, > + "IPC failed: unknown err,STS=0x%x, CMD=0x%x\n", > + status, ipcdev.cmd); > + } > + > + return ret; > +} > + > +/** > + * intel_punit_ipc_simple_command() - Simple IPC command > + * @cmd: IPC command code. > + * @para1: First 8bit parameter, set 0 if invalid. > + * @para2: Second 8bit parameter, set 0 if invalid. > + * > + * Send a IPC command to Punit when there is no data transaction > + * > + * Return: an IPC error code or 0 on success. > + */ > +int intel_punit_ipc_simple_command(int cmd, int para1, int para2) > +{ > + int ret; > + > + mutex_lock(&ipcdev.lock); > + ret = intel_punit_ipc_send_command(CMD_RUN | > + para2 << CMD_PARA2_SHIFT | > + para1 << CMD_PARA1_SHIFT | cmd); > + if (ret) > + goto out; > + ret = intel_punit_ipc_check_status(); > +out: > + mutex_unlock(&ipcdev.lock); > + return ret; > +} > +EXPORT_SYMBOL(intel_punit_ipc_simple_command); > + > +/** > + * intel_punit_ipc_command() - IPC command with data and pointers > + * @cmd: IPC command code. > + * @para1: First 8bit parameter, set 0 if invalid. > + * @para2: Second 8bit parameter, set 0 if invalid. > + * @in: Input data, 32bit for BIOS cmd, two 32bit for GTD and ISPD. > + * @out: Output data. > + * > + * Send a IPC command to Punit with data transaction > + * > + * Return: an IPC error code or 0 on success. > + */ > +int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out) > +{ > + int ret; > + > + mutex_lock(&ipcdev.lock); > + ipc_write_data_low(*in); > + if (ipcdev.type == GTDRIVER_MAILBOX || > + ipcdev.type == ISPDRIVER_MAILBOX) { > + in++; > + ipc_write_data_high(*in); > + } > + ret = intel_punit_ipc_send_command(CMD_RUN | > + para2 << CMD_PARA2_SHIFT | > + para1 << CMD_PARA1_SHIFT | cmd); > + if (ret) > + goto out; > + ret = intel_punit_ipc_check_status(); > + *out = ipc_read_data_low(); > + if (ipcdev.type == GTDRIVER_MAILBOX || > + ipcdev.type == ISPDRIVER_MAILBOX) { > + out++; > + *out = ipc_read_data_high(); > + } > +out: > + mutex_unlock(&ipcdev.lock); > + return ret; > +} > +EXPORT_SYMBOL_GPL(intel_punit_ipc_command); > + > +static irqreturn_t intel_punit_ioc(int irq, void *dev_id) > +{ > + complete(&ipcdev.cmd_complete); > + return IRQ_HANDLED; > +} > + > +static int intel_punit_get_bars(struct platform_device *pdev) > +{ > + struct resource *res0, *res1; > + void __iomem *addr; > + int size; > + int ret; > + > + res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!res0) { > + dev_err(&pdev->dev, "Failed to get iomem resource\n"); > + return -EINVAL; > + } > + size = resource_size(res0); > + if (!request_mem_region(res0->start, size, pdev->name)) { > + dev_err(&pdev->dev, "Failed to request iomem resouce\n"); > + return -EBUSY; > + } > + > + res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + if (!res1) { > + dev_err(&pdev->dev, "Failed to get iomem resource1\n"); > + return -EINVAL; > + } > + size = resource_size(res1); > + if (!request_mem_region(res1->start, size, pdev->name)) { > + dev_err(&pdev->dev, "Failed to request iomem resouce1\n"); > + ret = -EBUSY; > + goto err_res1; > + } > + > + addr = ioremap_nocache(res0->start, > + resource_size(res0) + resource_size(res1)); > + if (!addr) { > + dev_err(&pdev->dev, "Failed to ioremap ipc base\n"); > + ret = -ENOMEM; > + goto err_map; > + } > + ipcdev.base[BIOS_MAILBOX] = addr; > + addr += MAILBOX_REGISTER_SPACE; > + ipcdev.base[GTDRIVER_MAILBOX] = addr; > + addr += MAILBOX_REGISTER_SPACE; > + ipcdev.base[ISPDRIVER_MAILBOX] = addr; > + > + return 0; > + > +err_map: > + release_mem_region(res1->start, resource_size(res1)); > +err_res1: > + release_mem_region(res0->start, resource_size(res0)); > + return ret; > +} > + > +static int intel_punit_ipc_probe(struct platform_device *pdev) > +{ > + int irq; > + int ret; > + > + irq = platform_get_irq(pdev, 0); > + if (irq < 0) { > + ipcdev.irq = 0; > + dev_warn(&pdev->dev, "Could not get irq number\n"); > + } else { > + if (request_irq(irq, intel_punit_ioc, IRQF_NO_SUSPEND, > + "intel_punit_ipc", &ipcdev)) { > + dev_err(&pdev->dev, "request irq %d\n", irq); > + return -EBUSY; > + } > + ipcdev.irq = irq; > + } > + > + ret = intel_punit_get_bars(pdev); > + if (ret) { > + if (ipcdev.irq) > + free_irq(ipcdev.irq, &ipcdev); > + return ret; > + } > + > + ipcdev.pdev = pdev; > + mutex_init(&ipcdev.lock); > + init_completion(&ipcdev.cmd_complete); > + return ret; > +} > + > +static int intel_punit_ipc_remove(struct platform_device *pdev) > +{ > + struct resource *res; > + > + if (ipcdev.irq) > + free_irq(ipcdev.irq, &ipcdev); > + iounmap(ipcdev.base[BIOS_MAILBOX]); > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (res) > + release_mem_region(res->start, resource_size(res)); > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + if (res) > + release_mem_region(res->start, resource_size(res)); > + return 0; > +} > + > +#ifdef CONFIG_ACPI > +static const struct acpi_device_id punit_ipc_acpi_ids[] = { > + {"INT34D4", 0} > +}; > +#endif > + > +static struct platform_driver intel_punit_ipc_driver = { > + .probe = intel_punit_ipc_probe, > + .remove = intel_punit_ipc_remove, > + .driver = { > + .name = "intel_punit_ipc", > + .acpi_match_table = ACPI_PTR(punit_ipc_acpi_ids), > + }, > +}; > + > +static int __init intel_punit_ipc_init(void) > +{ > + return platform_driver_register(&intel_punit_ipc_driver); > +} > + > +static void __exit intel_punit_ipc_exit(void) > +{ > + platform_driver_unregister(&intel_punit_ipc_driver); > +} > + > +MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>"); > +MODULE_DESCRIPTION("Intel Punit IPC driver"); > +MODULE_LICENSE("GPL"); > + > +/* Some modules are dependent on this, so init earlier */ > +fs_initcall(intel_punit_ipc_init); > +module_exit(intel_punit_ipc_exit); > -- > 1.8.3.2 > >
On Wed, Aug 05, 2015 at 02:25:13PM -0700, Darren Hart wrote: > On Fri, Jul 31, 2015 at 11:58:56PM +0800, Qipeng Zha wrote: > > This driver provides support for Punit mailbox IPC on Intel platforms. > > The heart of the Punit is the Foxton microcontroller and its firmware, > > which provide mailbox interface for power management usage. > > > > Mika, Andriy: > > I'm traveling over the next few days and could use some help ensuring this new > driver receives some additional review. If you can, I'd appreciate your > thoughts. Sure, no problem. > > Signed-off-by: Qipeng Zha <qipeng.zha@intel.com> > > --- > > arch/x86/include/asm/intel_punit_ipc.h | 101 +++++++++ > > drivers/platform/x86/Kconfig | 6 + > > drivers/platform/x86/Makefile | 1 + > > drivers/platform/x86/intel_punit_ipc.c | 388 +++++++++++++++++++++++++++++++++ > > 4 files changed, 496 insertions(+) > > create mode 100644 arch/x86/include/asm/intel_punit_ipc.h > > create mode 100644 drivers/platform/x86/intel_punit_ipc.c > > > > diff --git a/arch/x86/include/asm/intel_punit_ipc.h b/arch/x86/include/asm/intel_punit_ipc.h > > new file mode 100644 > > index 0000000..08e3e14 > > --- /dev/null > > +++ b/arch/x86/include/asm/intel_punit_ipc.h > > @@ -0,0 +1,101 @@ > > +#ifndef _ASM_X86_INTEL_PUNIT_IPC_H_ > > +#define _ASM_X86_INTEL_PUNIT_IPC_H_ > > + > > +/* Commands supported on GLM core, are handled by different bars, > > + * unify these commands together here > > + */ > > +#define IPC_BIOS_PUNIT_CMD_BASE 0x00 > > +#define IPC_GTD_PUNIT_CMD_BASE 0x20 > > +#define IPC_ISPD_PUNIT_CMD_BASE 0x40 > > + > > +/* BIOS => Pcode commands */ > > +#define IPC_BIOS_PUNIT_CMD_ZERO (IPC_BIOS_PUNIT_CMD_BASE + 0x00) > > +#define IPC_BIOS_PUNIT_CMD_VR_INTERFACE (IPC_BIOS_PUNIT_CMD_BASE + 0x01) > > +#define IPC_BIOS_PUNIT_CMD_READ_PCS (IPC_BIOS_PUNIT_CMD_BASE + 0x02) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_PCS (IPC_BIOS_PUNIT_CMD_BASE + 0x03) > > +#define IPC_BIOS_PUNIT_CMD_READ_PCU_CONFIG (IPC_BIOS_PUNIT_CMD_BASE + 0x04) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_PCU_CONFIG (IPC_BIOS_PUNIT_CMD_BASE + 0x05) > > +#define IPC_BIOS_PUNIT_CMD_READ_PL1_SETTING (IPC_BIOS_PUNIT_CMD_BASE + 0x06) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_PL1_SETTING (IPC_BIOS_PUNIT_CMD_BASE + 0x07) > > +#define IPC_BIOS_PUNIT_CMD_TRIGGER_VDD_RAM (IPC_BIOS_PUNIT_CMD_BASE + 0x08) > > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_INFO (IPC_BIOS_PUNIT_CMD_BASE + 0x09) > > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_TRACE_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x0a) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_TRACE_CTRL \ > > + (IPC_BIOS_PUNIT_CMD_BASE + 0x0b) > > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_EVENT_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x0c) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_EVENT_CTRL \ > > + (IPC_BIOS_PUNIT_CMD_BASE + 0x0d) > > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_TRACE (IPC_BIOS_PUNIT_CMD_BASE + 0x0e) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_TRACE (IPC_BIOS_PUNIT_CMD_BASE + 0x0f) > > +#define IPC_BIOS_PUNIT_CMD_READ_TELE_EVENT (IPC_BIOS_PUNIT_CMD_BASE + 0x10) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_EVENT (IPC_BIOS_PUNIT_CMD_BASE + 0x11) > > +#define IPC_BIOS_PUNIT_CMD_READ_MODULE_TEMP (IPC_BIOS_PUNIT_CMD_BASE + 0x12) > > +#define IPC_BIOS_PUNIT_CMD_RESERVED (IPC_BIOS_PUNIT_CMD_BASE + 0x13) > > +#define IPC_BIOS_PUNIT_CMD_READ_VOLTAGE_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x14) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_VOLTAGE_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x15) > > +#define IPC_BIOS_PUNIT_CMD_READ_RATIO_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x16) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_RATIO_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x17) > > +#define IPC_BIOS_PUNIT_CMD_READ_VF_GL_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x18) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_VF_GL_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x19) > > +#define IPC_BIOS_PUNIT_CMD_READ_FM_SOC_TEMP_THRESH \ > > + (IPC_BIOS_PUNIT_CMD_BASE + 0x1a) > > +#define IPC_BIOS_PUNIT_CMD_WRITE_FM_SOC_TEMP_THRESH \ > > + (IPC_BIOS_PUNIT_CMD_BASE + 0x1b) > > + > > +/*GT Driver => Pcode commands*/ > > +#define IPC_GTD_PUNIT_CMD_ZERO (IPC_GTD_PUNIT_CMD_BASE + 0x00) > > +#define IPC_GTD_PUNIT_CMD_CONFIG (IPC_GTD_PUNIT_CMD_BASE + 0x01) > > +#define IPC_GTD_PUNIT_CMD_READ_ICCP_LIC_CDYN_SCAL \ > > + (IPC_GTD_PUNIT_CMD_BASE + 0x02) > > +#define IPC_GTD_PUNIT_CMD_WRITE_ICCP_LIC_CDYN_SCAL \ > > + (IPC_GTD_PUNIT_CMD_BASE + 0x03) > > +#define IPC_GTD_PUNIT_CMD_GET_WM_VAL (IPC_GTD_PUNIT_CMD_BASE + 0x06) > > +#define IPC_GTD_PUNIT_CMD_WRITE_CONFIG_WISHREQ (IPC_GTD_PUNIT_CMD_BASE + 0x07) > > +#define IPC_GTD_PUNIT_CMD_READ_REQ_DUTY_CYCLE (IPC_GTD_PUNIT_CMD_BASE + 0x16) > > +#define IPC_GTD_PUNIT_CMD_DIS_VOL_FREQ_CHANGE_REQUEST \ > > + (IPC_GTD_PUNIT_CMD_BASE + 0x17) > > +#define IPC_GTD_PUNIT_CMD_DYNA_DUTY_CYCLE_CTRL (IPC_GTD_PUNIT_CMD_BASE + 0x1a) > > +#define IPC_GTD_PUNIT_CMD_DYNA_DUTY_CYCLE_TUNING \ > > + (IPC_GTD_PUNIT_CMD_BASE + 0x1c) > > + > > +/* ISP Driver => Pcode commands */ > > +#define IPC_ISPD_PUNIT_CMD_ZERO (IPC_ISPD_PUNIT_CMD_BASE + 0x00) > > +#define IPC_ISPD_PUNIT_CMD_CONFIG (IPC_ISPD_PUNIT_CMD_BASE + 0x01) > > +#define IPC_ISPD_PUNIT_CMD_GET_ISP_LTR_VAL (IPC_ISPD_PUNIT_CMD_BASE + 0x02) > > +#define IPC_ISPD_PUNIT_CMD_ACCESS_IU_FREQ_BOUNDS \ > > + (IPC_ISPD_PUNIT_CMD_BASE + 0x03) > > +#define IPC_ISPD_PUNIT_CMD_READ_CDYN_LEVEL (IPC_ISPD_PUNIT_CMD_BASE + 0x04) > > +#define IPC_ISPD_PUNIT_CMD_WRITE_CDYN_LEVEL (IPC_ISPD_PUNIT_CMD_BASE + 0x05) > > +#define IPC_ISPD_PUNIT_CMD_MAX (IPC_ISPD_PUNIT_CMD_BASE + 0x06) > > + > > +/* Error codes */ > > +#define IPC_ERR_SUCCESS 0 > > +#define IPC_ERR_INVALID_CMD 1 > > +#define IPC_ERR_INVALID_PARAMETER 2 > > +#define IPC_ERR_CMD_TIMEOUT 3 > > +#define IPC_ERR_CMD_LOCKED 4 > > +#define IPC_ERR_INVALID_VR_ID 5 > > +#define IPC_ERR_VR_ERR 6 > > + > > +#if IS_ENABLED(CONFIG_INTEL_PUNIT_IPC) > > + > > +int intel_punit_ipc_simple_command(int cmd, int para1, int para2); > > +int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out); So is there going to be in-kernel user for this driver? > > + > > +#else > > + > > +static intline int intel_punit_ipc_simple_command(int cmd, > > + int para1, int para2); > > +{ > > + return -EINVAL; > > +} > > + > > +static inline int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, > > + u32 *in, u32 *out); > > +{ > > + return -EINVAL; > > +} > > + > > +#endif /*CONFIG_INTEL_PUNIT_IPC*/ > > + > > +#endif > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig > > index 346f1fd..42ada9b 100644 > > --- a/drivers/platform/x86/Kconfig > > +++ b/drivers/platform/x86/Kconfig > > @@ -891,4 +891,10 @@ config INTEL_PMC_IPC > > The PMC is an ARC processor which defines IPC commands for communication > > with other entities in the CPU. > > > > +config INTEL_PUNIT_IPC > > + tristate "Intel PUNIT IPC Driver" > > + default y I'm sure it does not need to be enabled by default. > > + ---help--- > > + IPC is used to bridge the communications between kernel and PUNIT > > + > > endif # X86_PLATFORM_DEVICES > > diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile > > index 1051372..eea765f 100644 > > --- a/drivers/platform/x86/Makefile > > +++ b/drivers/platform/x86/Makefile > > @@ -59,3 +59,4 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o > > obj-$(CONFIG_PVPANIC) += pvpanic.o > > obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o > > obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o > > +obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o > > diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c > > new file mode 100644 > > index 0000000..78cb794 > > --- /dev/null > > +++ b/drivers/platform/x86/intel_punit_ipc.c > > @@ -0,0 +1,388 @@ > > +/* > > + * intel_punit_ipc.c: Driver for the Intel Punit Mailbox IPC mechanism Drop the file name here. > > + * > > + * (C) Copyright 2015 Intel Corporation > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * The heart of the Punit is the Foxton microcontroller and its firmware, > > + * which provide mailbox interface for power management usage. > > + */ > > + > > +#include <linux/module.h> > > +#include <linux/delay.h> > > +#include <linux/errno.h> > > +#include <linux/init.h> > > +#include <linux/device.h> > > +#include <linux/pm.h> > > +#include <linux/acpi.h> > > +#include <linux/interrupt.h> > > +#include <linux/kernel.h> > > +#include <linux/bitops.h> > > +#include <linux/atomic.h> > > +#include <linux/notifier.h> > > +#include <linux/suspend.h> > > +#include <linux/platform_device.h> Are you sure you need all the above headers? > > +#include <asm/intel_punit_ipc.h> > > + > > +/* Mailbox registers */ > > +#define MAILBOX_DATA_LOW 0x0 > > +#define MAILBOX_INTERFACE 0x4 > > +#define CMD_RUN (1 << 31) > > +#define CMD_ERRCODE_MASK 0xFF > > +#define CMD_PARA1_SHIFT 8 > > +#define CMD_PARA2_SHIFT 16 > > +#define CMD_MASK 0xFF > > +#define MAILBOX_DATA_HIGH 0x8 > > + > > +#define MAILBOX_REGISTER_SPACE 0x10 > > + > > +#define CMD_TIMEOUT_SECONDS 3 > > + > > +/* Three external mailbox */ > > +enum mailbox_type { > > + BIOS_MAILBOX, > > + GTDRIVER_MAILBOX, > > + ISPDRIVER_MAILBOX, > > + RESERVED_MAILBOX, > > +}; > > + > > +struct intel_punit_ipc_controller { > > + struct platform_device *pdev; > > + struct mutex lock; > > + void __iomem *base[RESERVED_MAILBOX]; > > + struct completion cmd_complete; > > + int irq; > > + > > + int cmd; > > + enum mailbox_type type; > > +}; > > + > > +static char *ipc_err_sources[] = { > > + [IPC_ERR_SUCCESS] = > > + "no error", > > + [IPC_ERR_INVALID_CMD] = > > + "invalid command", > > + [IPC_ERR_INVALID_PARAMETER] = > > + "invalid parameter", > > + [IPC_ERR_CMD_TIMEOUT] = > > + "command timeout", > > + [IPC_ERR_CMD_LOCKED] = > > + "command locked", > > + [IPC_ERR_INVALID_VR_ID] = > > + "invalid vr id", > > + [IPC_ERR_VR_ERR] = > > + "vr error", > > +}; > > + > > +static struct intel_punit_ipc_controller ipcdev; Why not to allocate the private structure at probe time? > > + > > +static inline u32 ipc_read_status(void) > > +{ > > + return readl(ipcdev.base[ipcdev.type] + MAILBOX_INTERFACE); > > +} > > + > > +static inline void ipc_write_cmd(u32 cmd) > > +{ > > + writel(cmd, ipcdev.base[ipcdev.type] + MAILBOX_INTERFACE); > > +} > > + > > +static inline u32 ipc_read_data_low(void) > > +{ > > + return readl(ipcdev.base[ipcdev.type] + MAILBOX_DATA_LOW); > > +} > > + > > +static inline u32 ipc_read_data_high(void) > > +{ > > + return readl(ipcdev.base[ipcdev.type] + MAILBOX_DATA_HIGH); > > +} > > + > > +static inline void ipc_write_data_low(u32 data) > > +{ > > + writel(data, ipcdev.base[ipcdev.type] + MAILBOX_DATA_LOW); > > +} > > + > > +static inline void ipc_write_data_high(u32 data) > > +{ > > + writel(data, ipcdev.base[ipcdev.type] + MAILBOX_DATA_HIGH); > > +} > > + > > +static int intel_punit_init_cmd(u32 cmd) > > +{ > > + cmd &= CMD_MASK; > > + if (cmd < IPC_BIOS_PUNIT_CMD_BASE) > > + return -EINVAL; > > + else if (cmd < IPC_GTD_PUNIT_CMD_BASE) > > + ipcdev.type = BIOS_MAILBOX; > > + else if (cmd < IPC_ISPD_PUNIT_CMD_BASE) > > + ipcdev.type = GTDRIVER_MAILBOX; > > + else if (cmd < IPC_ISPD_PUNIT_CMD_MAX) > > + ipcdev.type = ISPDRIVER_MAILBOX; > > + else > > + return -EINVAL; > > + > > + return 0; return -EINVAL and drop else > > +} > > + > > +static int intel_punit_ipc_send_command(u32 cmd) > > +{ > > + int ret; > > + > > + ret = intel_punit_init_cmd(cmd); > > + if (ret) > > + return ret; > > + ipcdev.cmd = cmd; > > + reinit_completion(&ipcdev.cmd_complete); > > + ipc_write_cmd(cmd); > > + return 0; > > +} > > + > > +static int intel_punit_ipc_check_status(void) > > +{ > > + int loops = CMD_TIMEOUT_SECONDS * USEC_PER_SEC; > > + int ret = 0; > > + int status; > > + int errcode; > > + > > + if (ipcdev.irq) { > > + if (0 == wait_for_completion_timeout( if (!wait_for_completion_timeout( > > + &ipcdev.cmd_complete, > > + CMD_TIMEOUT_SECONDS * HZ)) { > > + dev_err(&ipcdev.pdev->dev, > > + "IPC timed out, IPC_CMD=0x%x\n", ipcdev.cmd); > > + return -ETIMEDOUT; > > + } > > + } else { > > + while ((ipc_read_status() & CMD_RUN) && --loops) > > + udelay(1); > > + if (!loops) { > > + dev_err(&ipcdev.pdev->dev, > > + "IPC timed out, IPC_CMD=0x%x\n", ipcdev.cmd); > > + return -ETIMEDOUT; > > + } > > + } > > + > > + status = ipc_read_status(); > > + errcode = status & CMD_ERRCODE_MASK; > > + if (errcode) { > > + ret = -EIO; > > + if (errcode < ARRAY_SIZE(ipc_err_sources)) > > + dev_err(&ipcdev.pdev->dev, > > + "IPC failed: %s, IPC_STS=0x%x, IPC_CMD=0x%x\n", > > + ipc_err_sources[errcode], status, ipcdev.cmd); > > + else > > + dev_err(&ipcdev.pdev->dev, > > + "IPC failed: unknown err,STS=0x%x, CMD=0x%x\n", > > + status, ipcdev.cmd); > > + } > > + > > + return ret; > > +} > > + > > +/** > > + * intel_punit_ipc_simple_command() - Simple IPC command > > + * @cmd: IPC command code. > > + * @para1: First 8bit parameter, set 0 if invalid. > > + * @para2: Second 8bit parameter, set 0 if invalid. > > + * > > + * Send a IPC command to Punit when there is no data transaction > > + * > > + * Return: an IPC error code or 0 on success. > > + */ > > +int intel_punit_ipc_simple_command(int cmd, int para1, int para2) > > +{ > > + int ret; > > + > > + mutex_lock(&ipcdev.lock); > > + ret = intel_punit_ipc_send_command(CMD_RUN | > > + para2 << CMD_PARA2_SHIFT | > > + para1 << CMD_PARA1_SHIFT | cmd); > > + if (ret) > > + goto out; > > + ret = intel_punit_ipc_check_status(); > > +out: > > + mutex_unlock(&ipcdev.lock); > > + return ret; > > +} > > +EXPORT_SYMBOL(intel_punit_ipc_simple_command); > > + > > +/** > > + * intel_punit_ipc_command() - IPC command with data and pointers > > + * @cmd: IPC command code. > > + * @para1: First 8bit parameter, set 0 if invalid. > > + * @para2: Second 8bit parameter, set 0 if invalid. > > + * @in: Input data, 32bit for BIOS cmd, two 32bit for GTD and ISPD. > > + * @out: Output data. > > + * > > + * Send a IPC command to Punit with data transaction > > + * > > + * Return: an IPC error code or 0 on success. > > + */ > > +int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out) > > +{ > > + int ret; > > + > > + mutex_lock(&ipcdev.lock); > > + ipc_write_data_low(*in); > > + if (ipcdev.type == GTDRIVER_MAILBOX || > > + ipcdev.type == ISPDRIVER_MAILBOX) { > > + in++; > > + ipc_write_data_high(*in); > > + } > > + ret = intel_punit_ipc_send_command(CMD_RUN | > > + para2 << CMD_PARA2_SHIFT | > > + para1 << CMD_PARA1_SHIFT | cmd); > > + if (ret) > > + goto out; > > + ret = intel_punit_ipc_check_status(); > > + *out = ipc_read_data_low(); > > + if (ipcdev.type == GTDRIVER_MAILBOX || > > + ipcdev.type == ISPDRIVER_MAILBOX) { > > + out++; > > + *out = ipc_read_data_high(); > > + } > > +out: > > + mutex_unlock(&ipcdev.lock); > > + return ret; > > +} > > +EXPORT_SYMBOL_GPL(intel_punit_ipc_command); > > + > > +static irqreturn_t intel_punit_ioc(int irq, void *dev_id) > > +{ > > + complete(&ipcdev.cmd_complete); > > + return IRQ_HANDLED; > > +} > > + > > +static int intel_punit_get_bars(struct platform_device *pdev) > > +{ > > + struct resource *res0, *res1; > > + void __iomem *addr; > > + int size; > > + int ret; > > + > > + res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + if (!res0) { > > + dev_err(&pdev->dev, "Failed to get iomem resource\n"); > > + return -EINVAL; > > + } > > + size = resource_size(res0); > > + if (!request_mem_region(res0->start, size, pdev->name)) { > > + dev_err(&pdev->dev, "Failed to request iomem resouce\n"); > > + return -EBUSY; > > + } Why not use devm_ here, like: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); addr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(addr)) return PTR_ERR(addr); > > + > > + res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); > > + if (!res1) { > > + dev_err(&pdev->dev, "Failed to get iomem resource1\n"); > > + return -EINVAL; > > + } > > + size = resource_size(res1); > > + if (!request_mem_region(res1->start, size, pdev->name)) { > > + dev_err(&pdev->dev, "Failed to request iomem resouce1\n"); > > + ret = -EBUSY; > > + goto err_res1; > > + } > > + > > + addr = ioremap_nocache(res0->start, > > + resource_size(res0) + resource_size(res1)); > > + if (!addr) { > > + dev_err(&pdev->dev, "Failed to ioremap ipc base\n"); > > + ret = -ENOMEM; > > + goto err_map; > > + } > > + ipcdev.base[BIOS_MAILBOX] = addr; > > + addr += MAILBOX_REGISTER_SPACE; > > + ipcdev.base[GTDRIVER_MAILBOX] = addr; > > + addr += MAILBOX_REGISTER_SPACE; > > + ipcdev.base[ISPDRIVER_MAILBOX] = addr; > > + > > + return 0; > > + > > +err_map: > > + release_mem_region(res1->start, resource_size(res1)); > > +err_res1: > > + release_mem_region(res0->start, resource_size(res0)); > > + return ret; > > +} > > + > > +static int intel_punit_ipc_probe(struct platform_device *pdev) > > +{ > > + int irq; > > + int ret; Looks better if you do int irq, ret; > > + > > + irq = platform_get_irq(pdev, 0); > > + if (irq < 0) { > > + ipcdev.irq = 0; > > + dev_warn(&pdev->dev, "Could not get irq number\n"); > > + } else { > > + if (request_irq(irq, intel_punit_ioc, IRQF_NO_SUSPEND, > > + "intel_punit_ipc", &ipcdev)) { > > + dev_err(&pdev->dev, "request irq %d\n", irq); > > + return -EBUSY; > > + } > > + ipcdev.irq = irq; > > + } devm_request_irq()? > > + > > + ret = intel_punit_get_bars(pdev); > > + if (ret) { > > + if (ipcdev.irq) > > + free_irq(ipcdev.irq, &ipcdev); Then you don't need all this... > > + return ret; > > + } > > + > > + ipcdev.pdev = pdev; > > + mutex_init(&ipcdev.lock); > > + init_completion(&ipcdev.cmd_complete); > > + return ret; > > +} > > + > > +static int intel_punit_ipc_remove(struct platform_device *pdev) > > +{ > > + struct resource *res; > > + > > + if (ipcdev.irq) > > + free_irq(ipcdev.irq, &ipcdev); > > + iounmap(ipcdev.base[BIOS_MAILBOX]); > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + if (res) > > + release_mem_region(res->start, resource_size(res)); > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > > + if (res) > > + release_mem_region(res->start, resource_size(res)); ...nor this. > > + return 0; > > +} > > + > > +#ifdef CONFIG_ACPI > > +static const struct acpi_device_id punit_ipc_acpi_ids[] = { > > + {"INT34D4", 0} > > +}; > > +#endif > > + > > +static struct platform_driver intel_punit_ipc_driver = { > > + .probe = intel_punit_ipc_probe, > > + .remove = intel_punit_ipc_remove, > > + .driver = { > > + .name = "intel_punit_ipc", > > + .acpi_match_table = ACPI_PTR(punit_ipc_acpi_ids), > > + }, > > +}; > > + > > +static int __init intel_punit_ipc_init(void) > > +{ > > + return platform_driver_register(&intel_punit_ipc_driver); > > +} > > + > > +static void __exit intel_punit_ipc_exit(void) > > +{ > > + platform_driver_unregister(&intel_punit_ipc_driver); > > +} > > + > > +MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>"); > > +MODULE_DESCRIPTION("Intel Punit IPC driver"); > > +MODULE_LICENSE("GPL"); GPLv2 > > + > > +/* Some modules are dependent on this, so init earlier */ > > +fs_initcall(intel_punit_ipc_init); > > +module_exit(intel_punit_ipc_exit); > > -- > > 1.8.3.2 > > > > > > -- > Darren Hart > Intel Open Source Technology Center -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
W0NjOiBNYXR0IHRvIGRpc2N1c3MgaVRDTyB0aGluZyBmb3VuZCBpbiBvbmUgb2YgdGhlIGRyaXZl cnNdDQoNCk9uIFdlZCwgMjAxNS0wOC0wNSBhdCAxNDoyNSAtMDcwMCwgRGFycmVuIEhhcnQgd3Jv dGU6DQo+IE9uIEZyaSwgSnVsIDMxLCAyMDE1IGF0IDExOjU4OjU2UE0gKzA4MDAsIFFpcGVuZyBa aGEgd3JvdGU6DQo+ID4gVGhpcyBkcml2ZXIgcHJvdmlkZXMgc3VwcG9ydCBmb3IgUHVuaXQgbWFp bGJveCBJUEMgb24gSW50ZWwgDQo+ID4gcGxhdGZvcm1zLg0KPiA+IFRoZSBoZWFydCBvZiB0aGUg UHVuaXQgaXMgdGhlIEZveHRvbiBtaWNyb2NvbnRyb2xsZXIgYW5kIGl0cyANCj4gPiBmaXJtd2Fy ZSwNCj4gPiB3aGljaCBwcm92aWRlIG1haWxib3ggaW50ZXJmYWNlIGZvciBwb3dlciBtYW5hZ2Vt ZW50IHVzYWdlLg0KPiA+IA0KPiANCj4gTWlrYSwgQW5kcml5Og0KPiANCj4gSSdtIHRyYXZlbGlu ZyBvdmVyIHRoZSBuZXh0IGZldyBkYXlzIGFuZCBjb3VsZCB1c2Ugc29tZSBoZWxwIGVuc3VyaW5n IA0KPiB0aGlzIG5ldw0KPiBkcml2ZXIgcmVjZWl2ZXMgc29tZSBhZGRpdGlvbmFsIHJldmlldy4g SWYgeW91IGNhbiwgSSdkIGFwcHJlY2lhdGUgDQo+IHlvdXINCj4gdGhvdWdodHMuDQoNClllcywg d2lsbCBkbyByaWdodCBub3cuDQoNCg0KRmlyc3Qgb2YgYWxsIHdlIGhhdmUgbWFueSB0aGluZ3Mg aGVyZSBhbmQgdGhlcmUgcmVsYXRlZCB0byBwb3dlcg0KY29udHJvbCBkZXZpY2VzIG9uIHZhcmlv dXMgSW50ZWwgaGFyZHdhcmUuDQoNCmFyY2gveDg2L3BsYXRmb3JtL2F0b20vcG1jX2F0b20uYw0K YXJjaC94ODYvcGxhdGZvcm0vYXRvbS9wdW5pdF9hdG9tX2RlYnVnLmMNCmRyaXZlcnMvbWZkL2lu dGVsX3NvY19wbWljX2NvcmUuYw0KZHJpdmVycy9wbGF0Zm9ybS94ODYvaW50ZWxfcG1jX2lwYy5j DQpkcml2ZXJzL3BsYXRmb3JtL3g4Ni9pbnRlbF9wbWljX2dwaW8uYw0KDQpTbywgd2hhdCBJIHNl ZSBpcyB0aGUgbWVuYWdlcmllIG9mIGRyaXZlcnMgc3ByZWFkIGluIHRoZSBzb3VyY2VzIHRyZWUu DQoNCkFuZCBvbiB0b3Agb2YgdGhhdCB3ZSBoYXZlIElPU0YgbWFpbGJveCBpbXBsZW1lbnRhdGlv bi4NCg0KU28sIHRoZSBtYWluIHF1ZXN0aW9ucyBhcmU6DQogLSBEb2VzIGFueSBvZiBhYm92ZSBj b3JyZWxhdGUgd2l0aCB3aGF0IHlvdSBhcmUgZG9pbmcgaW4gdGhpcyBkcml2ZXI/DQogLSBJcyBQ VW5pdCBhY2Nlc3NpYmxlIHZpYSBJT1NGIG1haWxib3g/DQogLSBXb3VsZCBpdCBiZSBnZW5lcmlj IGRyaXZlciBmb3IgbWFueSBJbnRlbCBwbGF0Zm9ybXMgb3Igb25seSBmb3IgZmV3Pw0KDQpBbHNv IHRoZSBuYW1lIG9mIHRoZSBtb2R1bGUgaXMgaW50ZWxfcHVuaXRfaXBjIHdoaWNoIGlzIHNvbWVo b3cgdXNlZCBpbg0KaW50ZWxfcG1jX2lwYy5jLg0KDQpNYXR0LCBieSB0aGUgd2F5IGludGVsX3Bt Y19pcGMuYyBtb2R1bGUgY3JlYXRlcyBpVENPIGRldmljZSAoTFBDIGJ1cykuDQpEb2VzIGl0IGxv b2sgY29ycmVjdD8NCg0KPiANCj4gPiBTaWduZWQtb2ZmLWJ5OiBRaXBlbmcgWmhhIDxxaXBlbmcu emhhQGludGVsLmNvbT4NCj4gPiAtLS0NCj4gPiAgYXJjaC94ODYvaW5jbHVkZS9hc20vaW50ZWxf cHVuaXRfaXBjLmggfCAxMDEgKysrKysrKysrDQo+ID4gIGRyaXZlcnMvcGxhdGZvcm0veDg2L0tj b25maWcgICAgICAgICAgIHwgICA2ICsNCj4gPiAgZHJpdmVycy9wbGF0Zm9ybS94ODYvTWFrZWZp bGUgICAgICAgICAgfCAgIDEgKw0KPiA+ICBkcml2ZXJzL3BsYXRmb3JtL3g4Ni9pbnRlbF9wdW5p dF9pcGMuYyB8IDM4OCANCj4gPiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4g PiAgNCBmaWxlcyBjaGFuZ2VkLCA0OTYgaW5zZXJ0aW9ucygrKQ0KPiA+ICBjcmVhdGUgbW9kZSAx MDA2NDQgYXJjaC94ODYvaW5jbHVkZS9hc20vaW50ZWxfcHVuaXRfaXBjLmgNCj4gPiAgY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvcGxhdGZvcm0veDg2L2ludGVsX3B1bml0X2lwYy5jDQo+ID4g DQo+ID4gZGlmZiAtLWdpdCBhL2FyY2gveDg2L2luY2x1ZGUvYXNtL2ludGVsX3B1bml0X2lwYy5o IA0KPiA+IGIvYXJjaC94ODYvaW5jbHVkZS9hc20vaW50ZWxfcHVuaXRfaXBjLmgNCj4gPiBuZXcg ZmlsZSBtb2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAuLjA4ZTNlMTQNCj4gPiAtLS0gL2Rl di9udWxsDQo+ID4gKysrIGIvYXJjaC94ODYvaW5jbHVkZS9hc20vaW50ZWxfcHVuaXRfaXBjLmgN Cj4gPiBAQCAtMCwwICsxLDEwMSBAQA0KPiA+ICsjaWZuZGVmIF9BU01fWDg2X0lOVEVMX1BVTklU X0lQQ19IXw0KPiA+ICsjZGVmaW5lICBfQVNNX1g4Nl9JTlRFTF9QVU5JVF9JUENfSF8NCj4gPiAr DQo+ID4gKy8qIENvbW1hbmRzIHN1cHBvcnRlZCBvbiBHTE0gY29yZSwgYXJlIGhhbmRsZWQgYnkg ZGlmZmVyZW50IGJhcnMsDQo+ID4gKyAqIHVuaWZ5IHRoZXNlIGNvbW1hbmRzIHRvZ2V0aGVyIGhl cmUNCj4gPiArICovDQo+ID4gKyNkZWZpbmUgSVBDX0JJT1NfUFVOSVRfQ01EX0JBU0UJCQkJMHgN Cj4gPiAwMA0KPiA+ICsjZGVmaW5lIElQQ19HVERfUFVOSVRfQ01EX0JBU0UJCQkJMHgyMA0KPiA+ ICsjZGVmaW5lIElQQ19JU1BEX1BVTklUX0NNRF9CQVNFCQkJCTB4DQo+ID4gNDANCg0KV2hhdCBh Ym91dCB1c2luZyBwcmVmaXggSVBDX1BVTklUXyBldmVyeXdoZXJlIGluIHRoaXMgZHJpdmVyPw0K DQo+ID4gKw0KPiA+ICsvKiBCSU9TID0+IFBjb2RlIGNvbW1hbmRzICovDQo+ID4gKyNkZWZpbmUg SVBDX0JJT1NfUFVOSVRfQ01EX1pFUk8JCQkoSVBDX0JJT1NfDQo+ID4gUFVOSVRfQ01EX0JBU0Ug KyAweDAwKQ0KDQpDYW4gd2UganVzdCBwcm92aWRlIGEgcGxhaW4gbnVtYmVyIHBlciBlYWNoIGNv bW1hbmQ/DQoNCk1vcmVvdmVyLCBkbyB3ZSBuZWVkIGFsbCBjb21tYW5kcyB0byBiZSBwcmVzZW50 IGluIHRoZSBmaXJzdCBwbGFjZT8NCkFueSB1c2VycyBmb3IgdGhlbSBhbGw/DQoNCj4gPiArI2Rl ZmluZSBJUENfQklPU19QVU5JVF9DTURfVlJfSU5URVJGQUNFCQkoSVBDX0JJT1NfDQo+ID4gUFVO SVRfQ01EX0JBU0UgKyAweDAxKQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9SRUFE X1BDUwkJKElQQ19CSU9TX1BVTklUX0NNDQo+ID4gRF9CQVNFICsgMHgwMikNCj4gPiArI2RlZmlu ZSBJUENfQklPU19QVU5JVF9DTURfV1JJVEVfUENTCQkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBE X0JBU0UgKyAweDAzKQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9SRUFEX1BDVV9D T05GSUcJKElQQ19CSU9TX1BVTklUX0NNDQo+ID4gRF9CQVNFICsgMHgwNCkNCj4gPiArI2RlZmlu ZSBJUENfQklPU19QVU5JVF9DTURfV1JJVEVfUENVX0NPTkZJRwkoSVBDX0JJT1NfUFVOSVRfQ00N Cj4gPiBEX0JBU0UgKyAweDA1KQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9SRUFE X1BMMV9TRVRUSU5HCShJUENfQklPU19QVU5JVF9DTQ0KPiA+IERfQkFTRSArIDB4MDYpDQo+ID4g KyNkZWZpbmUgSVBDX0JJT1NfUFVOSVRfQ01EX1dSSVRFX1BMMV9TRVRUSU5HCShJUENfQklPU19Q VU5JVF9DTQ0KPiA+IERfQkFTRSArIDB4MDcpDQo+ID4gKyNkZWZpbmUgSVBDX0JJT1NfUFVOSVRf Q01EX1RSSUdHRVJfVkREX1JBTQkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAweDA4 KQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9SRUFEX1RFTEVfSU5GTwkoSVBDX0JJ T1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAweDA5KQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BV TklUX0NNRF9SRUFEX1RFTEVfVFJBQ0VfQ1RSTAkoSVBDX0JJT1NfDQo+ID4gUFVOSVRfQ01EX0JB U0UgKyAweDBhKQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9XUklURV9URUxFX1RS QUNFX0NUUkwgXA0KPiA+ICsJCQkJCQkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAw eDBiKQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9SRUFEX1RFTEVfRVZFTlRfQ1RS TAkoSVBDX0JJT1NfDQo+ID4gUFVOSVRfQ01EX0JBU0UgKyAweDBjKQ0KPiA+ICsjZGVmaW5lIElQ Q19CSU9TX1BVTklUX0NNRF9XUklURV9URUxFX0VWRU5UX0NUUkwgXA0KPiA+ICsJCQkJCQkoSVBD X0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAweDBkKQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9T X1BVTklUX0NNRF9SRUFEX1RFTEVfVFJBQ0UJKElQQ19CSU9TX1BVTklUX0NNDQo+ID4gRF9CQVNF ICsgMHgwZSkNCj4gPiArI2RlZmluZSBJUENfQklPU19QVU5JVF9DTURfV1JJVEVfVEVMRV9UUkFD RQkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAweDBmKQ0KPiA+ICsjZGVmaW5lIElQ Q19CSU9TX1BVTklUX0NNRF9SRUFEX1RFTEVfRVZFTlQJKElQQ19CSU9TX1BVTklUX0NNDQo+ID4g RF9CQVNFICsgMHgxMCkNCj4gPiArI2RlZmluZSBJUENfQklPU19QVU5JVF9DTURfV1JJVEVfVEVM RV9FVkVOVAkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAweDExKQ0KPiA+ICsjZGVm aW5lIElQQ19CSU9TX1BVTklUX0NNRF9SRUFEX01PRFVMRV9URU1QCShJUENfQklPU19QVU5JVF9D TQ0KPiA+IERfQkFTRSArIDB4MTIpDQo+ID4gKyNkZWZpbmUgSVBDX0JJT1NfUFVOSVRfQ01EX1JF U0VSVkVECQkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAweDEzKQ0KPiA+ICsjZGVm aW5lIElQQ19CSU9TX1BVTklUX0NNRF9SRUFEX1ZPTFRBR0VfT1ZFUgkoSVBDX0JJT1NfUFVOSVRf Q00NCj4gPiBEX0JBU0UgKyAweDE0KQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9X UklURV9WT0xUQUdFX09WRVIJKElQQ19CSU9TX1BVTklUX0NNDQo+ID4gRF9CQVNFICsgMHgxNSkN Cj4gPiArI2RlZmluZSBJUENfQklPU19QVU5JVF9DTURfUkVBRF9SQVRJT19PVkVSCShJUENfQklP U19QVU5JVF9DTQ0KPiA+IERfQkFTRSArIDB4MTYpDQo+ID4gKyNkZWZpbmUgSVBDX0JJT1NfUFVO SVRfQ01EX1dSSVRFX1JBVElPX09WRVIJKElQQ19CSU9TX1BVTklUX0NNDQo+ID4gRF9CQVNFICsg MHgxNykNCj4gPiArI2RlZmluZSBJUENfQklPU19QVU5JVF9DTURfUkVBRF9WRl9HTF9DVFJMCShJ UENfQklPU19QVU5JVF9DTQ0KPiA+IERfQkFTRSArIDB4MTgpDQo+ID4gKyNkZWZpbmUgSVBDX0JJ T1NfUFVOSVRfQ01EX1dSSVRFX1ZGX0dMX0NUUkwJKElQQ19CSU9TX1BVTklUX0NNDQo+ID4gRF9C QVNFICsgMHgxOSkNCj4gPiArI2RlZmluZSBJUENfQklPU19QVU5JVF9DTURfUkVBRF9GTV9TT0Nf VEVNUF9USFJFU0ggXA0KPiA+ICsJCQkJCQkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0Ug KyAweDFhKQ0KPiA+ICsjZGVmaW5lIElQQ19CSU9TX1BVTklUX0NNRF9XUklURV9GTV9TT0NfVEVN UF9USFJFU0ggXA0KPiA+ICsJCQkJCQkoSVBDX0JJT1NfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAw eDFiKQ0KPiA+ICsNCj4gPiArLypHVCBEcml2ZXIgPT4gUGNvZGUgY29tbWFuZHMqLw0KPiA+ICsj ZGVmaW5lIElQQ19HVERfUFVOSVRfQ01EX1pFUk8JCQkoSVBDX0dURF9QVU5JVF9DTUQNCj4gPiBf QkFTRSArIDB4MDApDQo+ID4gKyNkZWZpbmUgSVBDX0dURF9QVU5JVF9DTURfQ09ORklHCQkoSVBD X0dURF9QVU5JVF9DTUQNCj4gPiBfQkFTRSArIDB4MDEpDQo+ID4gKyNkZWZpbmUgSVBDX0dURF9Q VU5JVF9DTURfUkVBRF9JQ0NQX0xJQ19DRFlOX1NDQUwgXA0KPiA+ICsJCQkJCQkoSVBDX0dURF9Q VU5JVF9DTUQNCj4gPiBfQkFTRSArIDB4MDIpDQo+ID4gKyNkZWZpbmUgSVBDX0dURF9QVU5JVF9D TURfV1JJVEVfSUNDUF9MSUNfQ0RZTl9TQ0FMIFwNCj4gPiArCQkJCQkJKElQQ19HVERfUFVOSVRf Q01EDQo+ID4gX0JBU0UgKyAweDAzKQ0KPiA+ICsjZGVmaW5lIElQQ19HVERfUFVOSVRfQ01EX0dF VF9XTV9WQUwJCShJUENfR1REX1BVTklUX0NNRA0KPiA+IF9CQVNFICsgMHgwNikNCj4gPiArI2Rl ZmluZSBJUENfR1REX1BVTklUX0NNRF9XUklURV9DT05GSUdfV0lTSFJFUQkoSVBDX0dURF9QVU5J VF9DTUQNCj4gPiBfQkFTRSArIDB4MDcpDQo+ID4gKyNkZWZpbmUgSVBDX0dURF9QVU5JVF9DTURf UkVBRF9SRVFfRFVUWV9DWUNMRQkoSVBDX0dURF9QVU5JVF9DTUQNCj4gPiBfQkFTRSArIDB4MTYp DQo+ID4gKyNkZWZpbmUgSVBDX0dURF9QVU5JVF9DTURfRElTX1ZPTF9GUkVRX0NIQU5HRV9SRVFV RVNUIFwNCj4gPiArCQkJCQkJKElQQ19HVERfUFVOSVRfQ01EDQo+ID4gX0JBU0UgKyAweDE3KQ0K PiA+ICsjZGVmaW5lIElQQ19HVERfUFVOSVRfQ01EX0RZTkFfRFVUWV9DWUNMRV9DVFJMCShJUENf R1REX1BVTklUX0NNRA0KPiA+IF9CQVNFICsgMHgxYSkNCj4gPiArI2RlZmluZSBJUENfR1REX1BV TklUX0NNRF9EWU5BX0RVVFlfQ1lDTEVfVFVOSU5HIFwNCj4gPiArCQkJCQkJKElQQ19HVERfUFVO SVRfQ01EDQo+ID4gX0JBU0UgKyAweDFjKQ0KPiA+ICsNCj4gPiArLyogSVNQIERyaXZlciA9PiBQ Y29kZSBjb21tYW5kcyAqLw0KPiA+ICsjZGVmaW5lIElQQ19JU1BEX1BVTklUX0NNRF9aRVJPCQkJ KElQQ19JU1BEXw0KPiA+IFBVTklUX0NNRF9CQVNFICsgMHgwMCkNCj4gPiArI2RlZmluZSBJUENf SVNQRF9QVU5JVF9DTURfQ09ORklHCQkoSVBDX0lTUERfUFVOSVRfQ00NCj4gPiBEX0JBU0UgKyAw eDAxKQ0KPiA+ICsjZGVmaW5lIElQQ19JU1BEX1BVTklUX0NNRF9HRVRfSVNQX0xUUl9WQUwJKElQ Q19JU1BEX1BVTklUX0NNDQo+ID4gRF9CQVNFICsgMHgwMikNCj4gPiArI2RlZmluZSBJUENfSVNQ RF9QVU5JVF9DTURfQUNDRVNTX0lVX0ZSRVFfQk9VTkRTIFwNCj4gPiArCQkJCQkJKElQQ19JU1BE X1BVTklUX0NNDQo+ID4gRF9CQVNFICsgMHgwMykNCj4gPiArI2RlZmluZSBJUENfSVNQRF9QVU5J VF9DTURfUkVBRF9DRFlOX0xFVkVMCShJUENfSVNQRF9QVU5JVF9DTQ0KPiA+IERfQkFTRSArIDB4 MDQpDQo+ID4gKyNkZWZpbmUgSVBDX0lTUERfUFVOSVRfQ01EX1dSSVRFX0NEWU5fTEVWRUwJKElQ Q19JU1BEX1BVTklUX0NNDQo+ID4gRF9CQVNFICsgMHgwNSkNCj4gPiArI2RlZmluZSBJUENfSVNQ RF9QVU5JVF9DTURfTUFYCQkJKElQQ19JU1BEX1BVTklUX0NNDQo+ID4gRF9CQVNFICsgMHgwNikN Cj4gPiArDQo+ID4gKy8qIEVycm9yIGNvZGVzICovDQo+ID4gKyNkZWZpbmUgSVBDX0VSUl9TVUND RVNTCQkJCTANCj4gPiArI2RlZmluZSBJUENfRVJSX0lOVkFMSURfQ01ECQkJMQ0KPiA+ICsjZGVm aW5lIElQQ19FUlJfSU5WQUxJRF9QQVJBTUVURVIJCTINCj4gPiArI2RlZmluZSBJUENfRVJSX0NN RF9USU1FT1VUCQkJMw0KPiA+ICsjZGVmaW5lIElQQ19FUlJfQ01EX0xPQ0tFRAkJCTQNCj4gPiAr I2RlZmluZSBJUENfRVJSX0lOVkFMSURfVlJfSUQJCQk1DQo+ID4gKyNkZWZpbmUgSVBDX0VSUl9W Ul9FUlIJCQkJNg0KPiA+ICsNCj4gPiArI2lmIElTX0VOQUJMRUQoQ09ORklHX0lOVEVMX1BVTklU X0lQQykNCj4gPiArDQo+ID4gK2ludCBpbnRlbF9wdW5pdF9pcGNfc2ltcGxlX2NvbW1hbmQoaW50 IGNtZCwgaW50IHBhcmExLCBpbnQgcGFyYTIpOw0KPiA+ICtpbnQgaW50ZWxfcHVuaXRfaXBjX2Nv bW1hbmQodTMyIGNtZCwgdTMyIHBhcmExLCB1MzIgcGFyYTIsIHUzMiANCj4gPiAqaW4sIHUzMiAq b3V0KTsNCj4gPiArDQo+ID4gKyNlbHNlDQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50bGluZSBpbnQg aW50ZWxfcHVuaXRfaXBjX3NpbXBsZV9jb21tYW5kKGludCBjbWQsDQo+ID4gKwkJCQkJCSAgaW50 IHBhcmExLCBpbnQgDQoNCg0KU2VlbXMgd2FzIG5ldmVyIGNvbXBpbGVkIHdpdGggZGlzYWJsZWQg b3B0aW9uLg0KDQo+ID4gcGFyYTIpOw0KPiA+ICt7DQo+ID4gKwlyZXR1cm4gLUVJTlZBTDsNCj4g PiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGlubGluZSBpbnQgaW50ZWxfcHVuaXRfaXBjX2NvbW1h bmQodTMyIGNtZCwgdTMyIHBhcmExLCB1MzIgDQo+ID4gcGFyYTIsDQo+ID4gKwkJCQkJICB1MzIg KmluLCB1MzIgKm91dCk7DQo+ID4gK3sNCj4gPiArCXJldHVybiAtRUlOVkFMOw0KPiA+ICt9DQo+ ID4gKw0KPiA+ICsjZW5kaWYgLypDT05GSUdfSU5URUxfUFVOSVRfSVBDKi8NCj4gPiArDQo+ID4g KyNlbmRpZg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BsYXRmb3JtL3g4Ni9LY29uZmlnIA0K PiA+IGIvZHJpdmVycy9wbGF0Zm9ybS94ODYvS2NvbmZpZw0KPiA+IGluZGV4IDM0NmYxZmQuLjQy YWRhOWIgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9wbGF0Zm9ybS94ODYvS2NvbmZpZw0KPiA+ ICsrKyBiL2RyaXZlcnMvcGxhdGZvcm0veDg2L0tjb25maWcNCj4gPiBAQCAtODkxLDQgKzg5MSwx MCBAQCBjb25maWcgSU5URUxfUE1DX0lQQw0KPiA+ICAJVGhlIFBNQyBpcyBhbiBBUkMgcHJvY2Vz c29yIHdoaWNoIGRlZmluZXMgSVBDIGNvbW1hbmRzIGZvciANCj4gPiBjb21tdW5pY2F0aW9uDQo+ ID4gIAl3aXRoIG90aGVyIGVudGl0aWVzIGluIHRoZSBDUFUuDQo+ID4gIA0KPiA+ICtjb25maWcg SU5URUxfUFVOSVRfSVBDDQo+ID4gKwl0cmlzdGF0ZSAiSW50ZWwgUFVOSVQgSVBDIERyaXZlciIN Cg0KUFVOSVQgLT4gUC1Vbml0ID8NCg0KPiA+ICsJZGVmYXVsdCB5DQo+ID4gKwktLS1oZWxwLS0t DQo+ID4gKwkgIElQQyBpcyB1c2VkIHRvIGJyaWRnZSB0aGUgY29tbXVuaWNhdGlvbnMgYmV0d2Vl biBrZXJuZWwgDQo+ID4gYW5kIFBVTklUDQoNCkRpdHRvLg0KDQo+ID4gKw0KPiA+ICBlbmRpZiAj IFg4Nl9QTEFURk9STV9ERVZJQ0VTDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGxhdGZvcm0v eDg2L01ha2VmaWxlIA0KPiA+IGIvZHJpdmVycy9wbGF0Zm9ybS94ODYvTWFrZWZpbGUNCj4gPiBp bmRleCAxMDUxMzcyLi5lZWE3NjVmIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvcGxhdGZvcm0v eDg2L01ha2VmaWxlDQo+ID4gKysrIGIvZHJpdmVycy9wbGF0Zm9ybS94ODYvTWFrZWZpbGUNCj4g PiBAQCAtNTksMyArNTksNCBAQCBvYmotJChDT05GSUdfSU5URUxfU01BUlRDT05ORUNUKQkrPSBp bnRlbA0KPiA+IC1zbWFydGNvbm5lY3Qubw0KPiA+ICBvYmotJChDT05GSUdfUFZQQU5JQykgICAg ICAgICAgICs9IHB2cGFuaWMubw0KPiA+ICBvYmotJChDT05GSUdfQUxJRU5XQVJFX1dNSSkJKz0g YWxpZW53YXJlLXdtaS5vDQo+ID4gIG9iai0kKENPTkZJR19JTlRFTF9QTUNfSVBDKQkrPSBpbnRl bF9wbWNfaXBjLm8NCj4gPiArb2JqLSQoQ09ORklHX0lOVEVMX1BVTklUX0lQQykJKz0gaW50ZWxf cHVuaXRfaXBjLm8NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wbGF0Zm9ybS94ODYvaW50ZWxf cHVuaXRfaXBjLmMgDQo+ID4gYi9kcml2ZXJzL3BsYXRmb3JtL3g4Ni9pbnRlbF9wdW5pdF9pcGMu Yw0KPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0DQo+ID4gaW5kZXggMDAwMDAwMC4uNzhjYjc5NA0K PiA+IC0tLSAvZGV2L251bGwNCj4gPiArKysgYi9kcml2ZXJzL3BsYXRmb3JtL3g4Ni9pbnRlbF9w dW5pdF9pcGMuYw0KPiA+IEBAIC0wLDAgKzEsMzg4IEBADQo+ID4gKy8qDQo+ID4gKyAqIGludGVs X3B1bml0X2lwYy5jOiBEcml2ZXIgZm9yIHRoZSBJbnRlbCBQdW5pdCBNYWlsYm94IElQQyANCj4g PiBtZWNoYW5pc20NCj4gPiArICoNCj4gPiArICogKEMpIENvcHlyaWdodCAyMDE1IEludGVsIENv cnBvcmF0aW9uDQo+ID4gKyAqDQo+ID4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJl OyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgDQo+ID4gbW9kaWZ5DQo+ID4gKyAqIGl0 IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lv biAyIA0KPiA+IGFzDQo+ID4gKyAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3Vu ZGF0aW9uLg0KPiA+ICsgKg0KPiA+ICsgKiBUaGUgaGVhcnQgb2YgdGhlIFB1bml0IGlzIHRoZSBG b3h0b24gbWljcm9jb250cm9sbGVyIGFuZCBpdHMgDQoNCg0KRGl0dG8uDQoNCj4gPiBmaXJtd2Fy ZSwNCj4gPiArICogd2hpY2ggcHJvdmlkZSBtYWlsYm94IGludGVyZmFjZSBmb3IgcG93ZXIgbWFu YWdlbWVudCB1c2FnZS4NCj4gPiArICovDQo+ID4gKw0KPiA+ICsjaW5jbHVkZSA8bGludXgvbW9k dWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPg0KPiA+ICsjaW5jbHVkZSA8bGlu dXgvZXJybm8uaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4NCj4gPiArI2luY2x1ZGUg PGxpbnV4L2RldmljZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvcG0uaD4NCj4gPiArI2luY2x1 ZGUgPGxpbnV4L2FjcGkuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPg0KPiA+ ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9iaXRvcHMu aD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2F0b21pYy5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgv bm90aWZpZXIuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3N1c3BlbmQuaD4NCj4gPiArI2luY2x1 ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPg0KPiA+ICsjaW5jbHVkZSA8YXNtL2ludGVsX3B1 bml0X2lwYy5oPg0KPiA+ICsNCj4gPiArLyogTWFpbGJveCByZWdpc3RlcnMgKi8NCj4gPiArI2Rl ZmluZSBNQUlMQk9YX0RBVEFfTE9XCQkweDANCj4gPiArI2RlZmluZSBNQUlMQk9YX0lOVEVSRkFD RQkJMHg0DQo+ID4gKyNkZWZpbmUJCUNNRF9SVU4JCQkoMSA8PCAzMSkNCj4gPiArI2RlZmluZQkJ Q01EX0VSUkNPREVfTUFTSwkweEZGDQo+ID4gKyNkZWZpbmUJCUNNRF9QQVJBMV9TSElGVAkJOA0K PiA+ICsjZGVmaW5lCQlDTURfUEFSQTJfU0hJRlQJCTE2DQo+ID4gKyNkZWZpbmUJCUNNRF9NQVNL CQkweEZGDQo+ID4gKyNkZWZpbmUgTUFJTEJPWF9EQVRBX0hJR0gJCTB4OA0KPiA+ICsNCj4gPiAr I2RlZmluZSBNQUlMQk9YX1JFR0lTVEVSX1NQQUNFCQkweDEwDQo+ID4gKw0KPiA+ICsjZGVmaW5l IENNRF9USU1FT1VUX1NFQ09ORFMJCTMNCj4gPiArDQo+ID4gKy8qIFRocmVlIGV4dGVybmFsIG1h aWxib3ggKi8NCj4gPiArZW51bSBtYWlsYm94X3R5cGUgew0KPiA+ICsJQklPU19NQUlMQk9YLA0K PiA+ICsJR1REUklWRVJfTUFJTEJPWCwNCj4gPiArCUlTUERSSVZFUl9NQUlMQk9YLA0KPiA+ICsJ UkVTRVJWRURfTUFJTEJPWCwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0cnVjdCBpbnRlbF9wdW5p dF9pcGNfY29udHJvbGxlciB7DQo+ID4gKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2Ow0K PiA+ICsJc3RydWN0IG11dGV4IGxvY2s7DQo+ID4gKwl2b2lkIF9faW9tZW0gKmJhc2VbUkVTRVJW RURfTUFJTEJPWF07DQoNCldoeSBub3QgdG8gdXNlIGV4cGxpY2l0bHkgb25lIGZpZWxkIHBlciBt YWlsYm94Pw0KQW5kIHRoZXJlZm9yZSByZW1vdmUgZW51bS4NCg0KPiA+ICsJc3RydWN0IGNvbXBs ZXRpb24gY21kX2NvbXBsZXRlOw0KPiA+ICsJaW50IGlycTsNCj4gPiArDQo+ID4gKwlpbnQgY21k Ow0KPiA+ICsJZW51bSBtYWlsYm94X3R5cGUgdHlwZTsNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0 YXRpYyBjaGFyICppcGNfZXJyX3NvdXJjZXNbXSA9IHsNCj4gPiArCVtJUENfRVJSX1NVQ0NFU1Nd ID0NCj4gPiArCQkibm8gZXJyb3IiLA0KPiA+ICsJW0lQQ19FUlJfSU5WQUxJRF9DTURdID0NCj4g PiArCQkiaW52YWxpZCBjb21tYW5kIiwNCj4gPiArCVtJUENfRVJSX0lOVkFMSURfUEFSQU1FVEVS XSA9DQo+ID4gKwkJImludmFsaWQgcGFyYW1ldGVyIiwNCj4gPiArCVtJUENfRVJSX0NNRF9USU1F T1VUXSA9DQo+ID4gKwkJImNvbW1hbmQgdGltZW91dCIsDQo+ID4gKwlbSVBDX0VSUl9DTURfTE9D S0VEXSA9DQo+ID4gKwkJImNvbW1hbmQgbG9ja2VkIiwNCj4gPiArCVtJUENfRVJSX0lOVkFMSURf VlJfSURdID0NCj4gPiArCQkiaW52YWxpZCB2ciBpZCIsDQo+ID4gKwlbSVBDX0VSUl9WUl9FUlJd ID0NCj4gPiArCQkidnIgZXJyb3IiLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIHN0cnVj dCBpbnRlbF9wdW5pdF9pcGNfY29udHJvbGxlciBpcGNkZXY7DQo+ID4gKw0KPiA+ICtzdGF0aWMg aW5saW5lIHUzMiBpcGNfcmVhZF9zdGF0dXModm9pZCkNCj4gPiArew0KPiA+ICsJcmV0dXJuIHJl YWRsKGlwY2Rldi5iYXNlW2lwY2Rldi50eXBlXSArIA0KPiA+IE1BSUxCT1hfSU5URVJGQUNFKTsN Cj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGlubGluZSB2b2lkIGlwY193cml0ZV9jbWQodTMy IGNtZCkNCj4gPiArew0KPiA+ICsJd3JpdGVsKGNtZCwgaXBjZGV2LmJhc2VbaXBjZGV2LnR5cGVd ICsgTUFJTEJPWF9JTlRFUkZBQ0UpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW5saW5l IHUzMiBpcGNfcmVhZF9kYXRhX2xvdyh2b2lkKQ0KPiA+ICt7DQo+ID4gKwlyZXR1cm4gcmVhZGwo aXBjZGV2LmJhc2VbaXBjZGV2LnR5cGVdICsgTUFJTEJPWF9EQVRBX0xPVyk7DQo+ID4gK30NCj4g PiArDQo+ID4gK3N0YXRpYyBpbmxpbmUgdTMyIGlwY19yZWFkX2RhdGFfaGlnaCh2b2lkKQ0KPiA+ ICt7DQo+ID4gKwlyZXR1cm4gcmVhZGwoaXBjZGV2LmJhc2VbaXBjZGV2LnR5cGVdICsgDQo+ID4g TUFJTEJPWF9EQVRBX0hJR0gpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW5saW5lIHZv aWQgaXBjX3dyaXRlX2RhdGFfbG93KHUzMiBkYXRhKQ0KPiA+ICt7DQo+ID4gKwl3cml0ZWwoZGF0 YSwgaXBjZGV2LmJhc2VbaXBjZGV2LnR5cGVdICsgTUFJTEJPWF9EQVRBX0xPVyk7DQo+ID4gK30N Cj4gPiArDQo+ID4gK3N0YXRpYyBpbmxpbmUgdm9pZCBpcGNfd3JpdGVfZGF0YV9oaWdoKHUzMiBk YXRhKQ0KPiA+ICt7DQo+ID4gKwl3cml0ZWwoZGF0YSwgaXBjZGV2LmJhc2VbaXBjZGV2LnR5cGVd ICsgDQo+ID4gTUFJTEJPWF9EQVRBX0hJR0gpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMg aW50IGludGVsX3B1bml0X2luaXRfY21kKHUzMiBjbWQpDQo+ID4gK3sNCj4gPiArCWNtZCAmPSBD TURfTUFTSzsNCj4gPiArCWlmIChjbWQgPCBJUENfQklPU19QVU5JVF9DTURfQkFTRSkNCj4gPiAr CQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArCWVsc2UgaWYgKGNtZCA8IElQQ19HVERfUFVOSVRfQ01E X0JBU0UpDQo+ID4gKwkJaXBjZGV2LnR5cGUgPSBCSU9TX01BSUxCT1g7DQo+ID4gKwllbHNlIGlm IChjbWQgPCBJUENfSVNQRF9QVU5JVF9DTURfQkFTRSkNCj4gPiArCQlpcGNkZXYudHlwZSA9IEdU RFJJVkVSX01BSUxCT1g7DQo+ID4gKwllbHNlIGlmIChjbWQgPCBJUENfSVNQRF9QVU5JVF9DTURf TUFYKQ0KPiA+ICsJCWlwY2Rldi50eXBlID0gSVNQRFJJVkVSX01BSUxCT1g7DQo+ID4gKwllbHNl DQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQoNCkl0IHNlZW1zIHlvdSBjYWxsIHRoaXMgZWFjaCB0 aW1lIHlvdSB3YW50IHRvIHNlbmQgYSBjb21tYW5kLg0KSXQgd291bGQgYmUgbmljZXIgd2l0aG91 dCBpcGNkZXYudHlwZSBzaW5jZSB5b3UgY3JlYXRlIGFuIGFydGlmaWNpYWwNCnR5cGUgaW4gdGhl IHNhbWUgY29kZSwgc28geW91IGFscmVhZHkga25vdyB0aGUgd2F5IGhvdyB0byBkbyB0aGF0LiBB bmQNCnRoZXJlIGlzIG1vcmUgY29uZnVzaW9uIHNpbmNlIHlvdXIgdHlwZSBpcyBwZXJtYW5lbnRs eSBtdXRhdGluZy4NCg0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ ICtzdGF0aWMgaW50IGludGVsX3B1bml0X2lwY19zZW5kX2NvbW1hbmQodTMyIGNtZCkNCj4gPiAr ew0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwlyZXQgPSBpbnRlbF9wdW5pdF9pbml0X2Nt ZChjbWQpOw0KPiA+ICsJaWYgKHJldCkNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJaXBjZGV2 LmNtZCA9IGNtZDsNCj4gPiArCXJlaW5pdF9jb21wbGV0aW9uKCZpcGNkZXYuY21kX2NvbXBsZXRl KTsNCj4gPiArCWlwY193cml0ZV9jbWQoY21kKTsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ ID4gKw0KPiA+ICtzdGF0aWMgaW50IGludGVsX3B1bml0X2lwY19jaGVja19zdGF0dXModm9pZCkN Cj4gPiArew0KPiA+ICsJaW50IGxvb3BzID0gQ01EX1RJTUVPVVRfU0VDT05EUyAqIFVTRUNfUEVS X1NFQzsNCj4gPiArCWludCByZXQgPSAwOw0KPiA+ICsJaW50IHN0YXR1czsNCj4gPiArCWludCBl cnJjb2RlOw0KPiA+ICsNCj4gPiArCWlmIChpcGNkZXYuaXJxKSB7DQo+ID4gKwkJaWYgKDAgPT0g d2FpdF9mb3JfY29tcGxldGlvbl90aW1lb3V0KA0KPiA+ICsJCQkJJmlwY2Rldi5jbWRfY29tcGxl dGUsDQoNCj4gPiArCQkJCUNNRF9USU1FT1VUX1NFQ09ORFMgKiBIWikpIHsNCg0KQ2FuIHlvdSB1 c2UgcGF0dGVybg0KaWYgKGZ1bmMoKSA9PSBjb25zdCkgaW5zdGVhZD8NCg0KPiA+ICsJCQlkZXZf ZXJyKCZpcGNkZXYucGRldi0+ZGV2LA0KPiA+ICsJCQkJIklQQyB0aW1lZCBvdXQsIElQQ19DTUQ9 MHgleFxuIiwgDQo+ID4gaXBjZGV2LmNtZCk7DQo+ID4gKwkJCXJldHVybiAtRVRJTUVET1VUOw0K PiA+ICsJCX0NCj4gPiArCX0gZWxzZSB7DQo+ID4gKwkJd2hpbGUgKChpcGNfcmVhZF9zdGF0dXMo KSAmIENNRF9SVU4pICYmIC0tbG9vcHMpDQo+ID4gKwkJCXVkZWxheSgxKTsNCj4gPiArCQlpZiAo IWxvb3BzKSB7DQo+ID4gKwkJCWRldl9lcnIoJmlwY2Rldi5wZGV2LT5kZXYsDQo+ID4gKwkJCQki SVBDIHRpbWVkIG91dCwgSVBDX0NNRD0weCV4XG4iLCANCj4gPiBpcGNkZXYuY21kKTsNCj4gPiAr CQkJcmV0dXJuIC1FVElNRURPVVQ7DQo+ID4gKwkJfQ0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXN0 YXR1cyA9IGlwY19yZWFkX3N0YXR1cygpOw0KPiA+ICsJZXJyY29kZSA9IHN0YXR1cyAmIENNRF9F UlJDT0RFX01BU0s7DQo+ID4gKwlpZiAoZXJyY29kZSkgew0KPiA+ICsJCXJldCA9IC1FSU87DQo+ ID4gKwkJaWYgKGVycmNvZGUgPCBBUlJBWV9TSVpFKGlwY19lcnJfc291cmNlcykpDQo+ID4gKwkJ CWRldl9lcnIoJmlwY2Rldi5wZGV2LT5kZXYsDQo+ID4gKwkJCQkiSVBDIGZhaWxlZDogJXMsIElQ Q19TVFM9MHgleCwgDQo+ID4gSVBDX0NNRD0weCV4XG4iLA0KPiA+ICsJCQkJaXBjX2Vycl9zb3Vy Y2VzW2VycmNvZGVdLCBzdGF0dXMsIA0KPiA+IGlwY2Rldi5jbWQpOw0KPiA+ICsJCWVsc2UNCj4g PiArCQkJZGV2X2VycigmaXBjZGV2LnBkZXYtPmRldiwNCj4gPiArCQkJCSJJUEMgZmFpbGVkOiB1 bmtub3duIGVycixTVFM9MHgleCwgDQo+ID4gQ01EPTB4JXhcbiIsDQo+ID4gKwkJCQlzdGF0dXMs IGlwY2Rldi5jbWQpOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30N Cj4gPiArDQo+ID4gKy8qKg0KPiA+ICsgKiBpbnRlbF9wdW5pdF9pcGNfc2ltcGxlX2NvbW1hbmQo KSAtIFNpbXBsZSBJUEMgY29tbWFuZA0KPiA+ICsgKiBAY21kOglJUEMgY29tbWFuZCBjb2RlLg0K PiA+ICsgKiBAcGFyYTE6CUZpcnN0IDhiaXQgcGFyYW1ldGVyLCBzZXQgMCBpZiBpbnZhbGlkLg0K PiA+ICsgKiBAcGFyYTI6CVNlY29uZCA4Yml0IHBhcmFtZXRlciwgc2V0IDAgaWYgaW52YWxpZC4N Cj4gPiArICoNCj4gPiArICogU2VuZCBhIElQQyBjb21tYW5kIHRvIFB1bml0IHdoZW4gdGhlcmUg aXMgbm8gZGF0YSB0cmFuc2FjdGlvbg0KPiA+ICsgKg0KPiA+ICsgKiBSZXR1cm46CWFuIElQQyBl cnJvciBjb2RlIG9yIDAgb24gc3VjY2Vzcy4NCj4gPiArICovDQo+ID4gK2ludCBpbnRlbF9wdW5p dF9pcGNfc2ltcGxlX2NvbW1hbmQoaW50IGNtZCwgaW50IHBhcmExLCBpbnQgcGFyYTIpDQo+ID4g K3sNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJbXV0ZXhfbG9jaygmaXBjZGV2LmxvY2sp Ow0KPiA+ICsJcmV0ID0gaW50ZWxfcHVuaXRfaXBjX3NlbmRfY29tbWFuZChDTURfUlVOIHwNCj4g PiArCQkJCQkgICBwYXJhMiA8PCANCj4gPiBDTURfUEFSQTJfU0hJRlQgfA0KPiA+ICsJCQkJCSAg IHBhcmExIDw8IA0KPiA+IENNRF9QQVJBMV9TSElGVCB8IGNtZCk7DQo+ID4gKwlpZiAocmV0KQ0K PiA+ICsJCWdvdG8gb3V0Ow0KPiA+ICsJcmV0ID0gaW50ZWxfcHVuaXRfaXBjX2NoZWNrX3N0YXR1 cygpOw0KPiA+ICtvdXQ6DQo+ID4gKwltdXRleF91bmxvY2soJmlwY2Rldi5sb2NrKTsNCj4gPiAr CXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArRVhQT1JUX1NZTUJPTChpbnRlbF9wdW5pdF9pcGNf c2ltcGxlX2NvbW1hbmQpOw0KPiA+ICsNCj4gPiArLyoqDQo+ID4gKyAqIGludGVsX3B1bml0X2lw Y19jb21tYW5kKCkgLSBJUEMgY29tbWFuZCB3aXRoIGRhdGEgYW5kIHBvaW50ZXJzDQo+ID4gKyAq IEBjbWQ6CUlQQyBjb21tYW5kIGNvZGUuDQo+ID4gKyAqIEBwYXJhMToJRmlyc3QgOGJpdCBwYXJh bWV0ZXIsIHNldCAwIGlmIGludmFsaWQuDQo+ID4gKyAqIEBwYXJhMjoJU2Vjb25kIDhiaXQgcGFy YW1ldGVyLCBzZXQgMCBpZiBpbnZhbGlkLg0KPiA+ICsgKiBAaW46CQlJbnB1dCBkYXRhLCAzMmJp dCBmb3IgQklPUyBjbWQsIHR3byAzMmJpdCANCj4gPiBmb3IgR1REIGFuZCBJU1BELg0KPiA+ICsg KiBAb3V0OglPdXRwdXQgZGF0YS4NCj4gPiArICoNCj4gPiArICogU2VuZCBhIElQQyBjb21tYW5k IHRvIFB1bml0IHdpdGggZGF0YSB0cmFuc2FjdGlvbg0KPiA+ICsgKg0KPiA+ICsgKiBSZXR1cm46 CWFuIElQQyBlcnJvciBjb2RlIG9yIDAgb24gc3VjY2Vzcy4NCj4gPiArICovDQo+ID4gK2ludCBp bnRlbF9wdW5pdF9pcGNfY29tbWFuZCh1MzIgY21kLCB1MzIgcGFyYTEsIHUzMiBwYXJhMiwgdTMy IA0KPiA+ICppbiwgdTMyICpvdXQpDQo+ID4gK3sNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ ICsJbXV0ZXhfbG9jaygmaXBjZGV2LmxvY2spOw0KPiA+ICsJaXBjX3dyaXRlX2RhdGFfbG93KCpp bik7DQo+ID4gKwlpZiAoaXBjZGV2LnR5cGUgPT0gR1REUklWRVJfTUFJTEJPWCB8fA0KPiA+ICsJ CQlpcGNkZXYudHlwZSA9PSBJU1BEUklWRVJfTUFJTEJPWCkgew0KPiA+ICsJCWluKys7DQo+ID4g KwkJaXBjX3dyaXRlX2RhdGFfaGlnaCgqaW4pOw0KDQoqKytpbg0KDQo+ID4gKwl9DQo+ID4gKwly ZXQgPSBpbnRlbF9wdW5pdF9pcGNfc2VuZF9jb21tYW5kKENNRF9SVU4gfA0KPiA+ICsJCQkJCSAg IHBhcmEyIDw8IA0KPiA+IENNRF9QQVJBMl9TSElGVCB8DQo+ID4gKwkJCQkJICAgcGFyYTEgPDwg DQo+ID4gQ01EX1BBUkExX1NISUZUIHwgY21kKTsNCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJZ290 byBvdXQ7DQo+ID4gKwlyZXQgPSBpbnRlbF9wdW5pdF9pcGNfY2hlY2tfc3RhdHVzKCk7DQo+ID4g Kwkqb3V0ID0gaXBjX3JlYWRfZGF0YV9sb3coKTsNCj4gPiArCWlmIChpcGNkZXYudHlwZSA9PSBH VERSSVZFUl9NQUlMQk9YIHx8DQo+ID4gKwkJCWlwY2Rldi50eXBlID09IElTUERSSVZFUl9NQUlM Qk9YKSB7DQo+ID4gKwkJb3V0Kys7DQo+ID4gKwkJKm91dCA9IGlwY19yZWFkX2RhdGFfaGlnaCgp Ow0KDQoqKytvdXQNCg0KPiA+ICsJfQ0KPiA+ICtvdXQ6DQo+ID4gKwltdXRleF91bmxvY2soJmlw Y2Rldi5sb2NrKTsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArRVhQT1JUX1NZTUJP TF9HUEwoaW50ZWxfcHVuaXRfaXBjX2NvbW1hbmQpOw0KPiA+ICsNCj4gPiArc3RhdGljIGlycXJl dHVybl90IGludGVsX3B1bml0X2lvYyhpbnQgaXJxLCB2b2lkICpkZXZfaWQpDQo+ID4gK3sNCj4g PiArCWNvbXBsZXRlKCZpcGNkZXYuY21kX2NvbXBsZXRlKTsNCj4gPiArCXJldHVybiBJUlFfSEFO RExFRDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBpbnRlbF9wdW5pdF9nZXRfYmFy cyhzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgcmVz b3VyY2UgKnJlczAsICpyZXMxOw0KPiA+ICsJdm9pZCBfX2lvbWVtICphZGRyOw0KPiA+ICsJaW50 IHNpemU7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCXJlczAgPSBwbGF0Zm9ybV9nZXRf cmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOw0KPiA+ICsJaWYgKCFyZXMwKSB7DQo+ ID4gKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiRmFpbGVkIHRvIGdldCBpb21lbSANCj4gPiByZXNv dXJjZVxuIik7DQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gKwlzaXplID0g cmVzb3VyY2Vfc2l6ZShyZXMwKTsNCj4gPiArCWlmICghcmVxdWVzdF9tZW1fcmVnaW9uKHJlczAt PnN0YXJ0LCBzaXplLCBwZGV2LT5uYW1lKSkgew0KPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwg IkZhaWxlZCB0byByZXF1ZXN0IGlvbWVtIA0KPiA+IHJlc291Y2VcbiIpOw0KPiA+ICsJCXJldHVy biAtRUJVU1k7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmVzMSA9IHBsYXRmb3JtX2dldF9yZXNv dXJjZShwZGV2LCBJT1JFU09VUkNFX01FTSwgMSk7DQo+ID4gKwlpZiAoIXJlczEpIHsNCj4gPiAr CQlkZXZfZXJyKCZwZGV2LT5kZXYsICJGYWlsZWQgdG8gZ2V0IGlvbWVtIA0KPiA+IHJlc291cmNl MVxuIik7DQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gKwlzaXplID0gcmVz b3VyY2Vfc2l6ZShyZXMxKTsNCj4gPiArCWlmICghcmVxdWVzdF9tZW1fcmVnaW9uKHJlczEtPnN0 YXJ0LCBzaXplLCBwZGV2LT5uYW1lKSkgew0KPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIkZh aWxlZCB0byByZXF1ZXN0IGlvbWVtIA0KPiA+IHJlc291Y2UxXG4iKTsNCj4gPiArCQlyZXQgPSAt RUJVU1k7DQo+ID4gKwkJZ290byBlcnJfcmVzMTsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlhZGRy ID0gaW9yZW1hcF9ub2NhY2hlKHJlczAtPnN0YXJ0LA0KPiA+ICsJCQkgICAgICAgcmVzb3VyY2Vf c2l6ZShyZXMwKSArIA0KPiA+IHJlc291cmNlX3NpemUocmVzMSkpOw0KPiA+ICsJaWYgKCFhZGRy KSB7DQo+ID4gKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiRmFpbGVkIHRvIGlvcmVtYXAgaXBjIA0K PiA+IGJhc2VcbiIpOw0KPiA+ICsJCXJldCA9IC1FTk9NRU07DQo+ID4gKwkJZ290byBlcnJfbWFw Ow0KPiA+ICsJfQ0KPiA+ICsJaXBjZGV2LmJhc2VbQklPU19NQUlMQk9YXSA9IGFkZHI7DQo+ID4g KwlhZGRyICs9IE1BSUxCT1hfUkVHSVNURVJfU1BBQ0U7DQo+ID4gKwlpcGNkZXYuYmFzZVtHVERS SVZFUl9NQUlMQk9YXSA9IGFkZHI7DQo+ID4gKwlhZGRyICs9IE1BSUxCT1hfUkVHSVNURVJfU1BB Q0U7DQo+ID4gKwlpcGNkZXYuYmFzZVtJU1BEUklWRVJfTUFJTEJPWF0gPSBhZGRyOw0KDQpXYWl0 LCBpcyB0aGlzIE1GRCBvciBqdXN0IHlvdSBsb2dpY2FsbHkgc3BsaXQgaXQuIElmIHRoZSBsYXR0 ZXIgaXMNCnRydWUsIHRoZW4gbWlnaHQgYmUgbm8gbmVlZCB0byBkaWZmZXJlbnRpYXRlIGFkZHJl c3Nlcy4NCg0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICsNCj4gPiArZXJyX21hcDoNCj4g PiArCXJlbGVhc2VfbWVtX3JlZ2lvbihyZXMxLT5zdGFydCwgcmVzb3VyY2Vfc2l6ZShyZXMxKSk7 DQo+ID4gK2Vycl9yZXMxOg0KPiA+ICsJcmVsZWFzZV9tZW1fcmVnaW9uKHJlczAtPnN0YXJ0LCBy ZXNvdXJjZV9zaXplKHJlczApKTsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ ID4gK3N0YXRpYyBpbnQgaW50ZWxfcHVuaXRfaXBjX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZp Y2UgKnBkZXYpDQo+ID4gK3sNCj4gPiArCWludCBpcnE7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsN Cj4gPiArCWlycSA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwgMCk7DQo+ID4gKwlpZiAoaXJxIDwg MCkgew0KPiA+ICsJCWlwY2Rldi5pcnEgPSAwOw0KPiA+ICsJCWRldl93YXJuKCZwZGV2LT5kZXYs ICJDb3VsZCBub3QgZ2V0IGlycSANCj4gPiBudW1iZXJcbiIpOw0KPiA+ICsJfSBlbHNlIHsNCj4g PiArCQlpZiAocmVxdWVzdF9pcnEoaXJxLCBpbnRlbF9wdW5pdF9pb2MsIA0KPiA+IElSUUZfTk9f U1VTUEVORCwNCj4gPiArCQkJCSJpbnRlbF9wdW5pdF9pcGMiLCAmaXBjZGV2KSkgew0KPiA+ICsJ CQlkZXZfZXJyKCZwZGV2LT5kZXYsICJyZXF1ZXN0IGlycSAlZFxuIiwgDQo+ID4gaXJxKTsNCj4g PiArCQkJcmV0dXJuIC1FQlVTWTsNCj4gPiArCQl9DQo+ID4gKwkJaXBjZGV2LmlycSA9IGlycTsN Cj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXQgPSBpbnRlbF9wdW5pdF9nZXRfYmFycyhwZGV2KTsN Cj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlpZiAoaXBjZGV2LmlycSkNCj4gPiArCQkJZnJlZV9p cnEoaXBjZGV2LmlycSwgJmlwY2Rldik7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4g PiArDQo+ID4gKwlpcGNkZXYucGRldiA9IHBkZXY7DQo+ID4gKwltdXRleF9pbml0KCZpcGNkZXYu bG9jayk7DQo+ID4gKwlpbml0X2NvbXBsZXRpb24oJmlwY2Rldi5jbWRfY29tcGxldGUpOw0KPiA+ ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBpbnRlbF9wdW5p dF9pcGNfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpDQo+ID4gK3sNCj4gPiAr CXN0cnVjdCByZXNvdXJjZSAqcmVzOw0KPiA+ICsNCj4gPiArCWlmIChpcGNkZXYuaXJxKQ0KPiA+ ICsJCWZyZWVfaXJxKGlwY2Rldi5pcnEsICZpcGNkZXYpOw0KPiA+ICsJaW91bm1hcChpcGNkZXYu YmFzZVtCSU9TX01BSUxCT1hdKTsNCj4gPiArCXJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJjZShw ZGV2LCBJT1JFU09VUkNFX01FTSwgMCk7DQo+ID4gKwlpZiAocmVzKQ0KPiA+ICsJCXJlbGVhc2Vf bWVtX3JlZ2lvbihyZXMtPnN0YXJ0LCANCj4gPiByZXNvdXJjZV9zaXplKHJlcykpOw0KPiA+ICsJ cmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVNLCAxKTsNCj4g PiArCWlmIChyZXMpDQo+ID4gKwkJcmVsZWFzZV9tZW1fcmVnaW9uKHJlcy0+c3RhcnQsIA0KPiA+ IHJlc291cmNlX3NpemUocmVzKSk7DQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4g PiArI2lmZGVmIENPTkZJR19BQ1BJDQoNCk5vIG5lZWQgdG8gaGF2ZSAjaWZkZWYgaGVyZS4NCg0K PiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGFjcGlfZGV2aWNlX2lkIHB1bml0X2lwY19hY3BpX2lk c1tdID0gew0KPiA+ICsJeyJJTlQzNEQ0IiwgMH0NCj4gPiArfTsNCj4gPiArI2VuZGlmDQo+ID4g Kw0KPiA+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpbnRlbF9wdW5pdF9pcGNfZHJp dmVyID0gew0KPiA+ICsJLnByb2JlID0gaW50ZWxfcHVuaXRfaXBjX3Byb2JlLA0KPiA+ICsJLnJl bW92ZSA9IGludGVsX3B1bml0X2lwY19yZW1vdmUsDQo+ID4gKwkuZHJpdmVyID0gew0KPiA+ICsJ CS5uYW1lID0gImludGVsX3B1bml0X2lwYyIsDQo+ID4gKwkJLmFjcGlfbWF0Y2hfdGFibGUgPSBB Q1BJX1BUUihwdW5pdF9pcGNfYWNwaV9pZHMpLA0KPiA+ICsJfSwNCj4gPiArfTsNCj4gPiArDQo+ ID4gK3N0YXRpYyBpbnQgX19pbml0IGludGVsX3B1bml0X2lwY19pbml0KHZvaWQpDQo+ID4gK3sN Cj4gPiArCXJldHVybiBwbGF0Zm9ybV9kcml2ZXJfcmVnaXN0ZXIoJmludGVsX3B1bml0X2lwY19k cml2ZXIpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBfX2V4aXQgaW50ZWxfcHVu aXRfaXBjX2V4aXQodm9pZCkNCj4gPiArew0KPiA+ICsJcGxhdGZvcm1fZHJpdmVyX3VucmVnaXN0 ZXIoJmludGVsX3B1bml0X2lwY19kcml2ZXIpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtNT0RVTEVf QVVUSE9SKCJaaGEgUWlwZW5nIDxxaXBlbmcuemhhQGludGVsLmNvbT4iKTsNCj4gPiArTU9EVUxF X0RFU0NSSVBUSU9OKCJJbnRlbCBQdW5pdCBJUEMgZHJpdmVyIik7DQo+ID4gK01PRFVMRV9MSUNF TlNFKCJHUEwiKTsNCj4gPiArDQo+ID4gKy8qIFNvbWUgbW9kdWxlcyBhcmUgZGVwZW5kZW50IG9u IHRoaXMsIHNvIGluaXQgZWFybGllciAqLw0KDQpTbywgaW5pdGNhbGxzIG1ha2Ugc2Vuc2Ugb25s eSBmb3IgYnVpbHQtaW4gZHJpdmVycy4gV2hpY2ggb25lIHdpbGwNCnJlcXVpcmUgdGhhdD8NCg0K PiA+ICtmc19pbml0Y2FsbChpbnRlbF9wdW5pdF9pcGNfaW5pdCk7DQo+ID4gK21vZHVsZV9leGl0 KGludGVsX3B1bml0X2lwY19leGl0KTsNCj4gPiAtLSANCj4gPiAxLjguMy4yDQo+ID4gDQo+ID4g DQo+IA0KDQotLSANCkFuZHkgU2hldmNoZW5rbyA8YW5kcml5LnNoZXZjaGVua29AaW50ZWwuY29t Pg0KSW50ZWwgRmlubGFuZCBPeQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KSW50ZWwgRmlubGFuZCBPeQpSZWdpc3Rl cmVkIEFkZHJlc3M6IFBMIDI4MSwgMDAxODEgSGVsc2lua2kgCkJ1c2luZXNzIElkZW50aXR5IENv ZGU6IDAzNTc2MDYgLSA0IApEb21pY2lsZWQgaW4gSGVsc2lua2kgCgpUaGlzIGUtbWFpbCBhbmQg YW55IGF0dGFjaG1lbnRzIG1heSBjb250YWluIGNvbmZpZGVudGlhbCBtYXRlcmlhbCBmb3IKdGhl IHNvbGUgdXNlIG9mIHRoZSBpbnRlbmRlZCByZWNpcGllbnQocykuIEFueSByZXZpZXcgb3IgZGlz dHJpYnV0aW9uCmJ5IG90aGVycyBpcyBzdHJpY3RseSBwcm9oaWJpdGVkLiBJZiB5b3UgYXJlIG5v dCB0aGUgaW50ZW5kZWQKcmVjaXBpZW50LCBwbGVhc2UgY29udGFjdCB0aGUgc2VuZGVyIGFuZCBk ZWxldGUgYWxsIGNvcGllcy4K -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 2015-08-10 at 16:04 +0100, Shevchenko, Andriy wrote: > > Matt, by the way intel_pmc_ipc.c module creates iTCO device (LPC bus). > Does it look correct? Yeah, it looks OK to me. Note there are changes queued up in Lee Jones' tree for changing the lpc_ich_info into itco_wdt_platform_data. Btw, is there a reason that intel_pmc_ipc doesn't use the mfd_* API since it's concerned with multiple functions? -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Aug 18, 2015 at 04:50:56PM +0100, Matt Fleming wrote: > On Mon, 2015-08-10 at 16:04 +0100, Shevchenko, Andriy wrote: > > > > Matt, by the way intel_pmc_ipc.c module creates iTCO device (LPC bus). > > Does it look correct? > > Yeah, it looks OK to me. Note there are changes queued up in Lee Jones' > tree for changing the lpc_ich_info into itco_wdt_platform_data. > > Btw, is there a reason that intel_pmc_ipc doesn't use the mfd_* API > since it's concerned with multiple functions? Qipeng? I saw the v2 come in, but didn't see this question addressed in the changelog.
On Tue, Aug 18, 2015 at 04:50:56PM +0100, Matt Fleming wrote: > On Mon, 2015-08-10 at 16:04 +0100, Shevchenko, Andriy wrote: > > > > Matt, by the way intel_pmc_ipc.c module creates iTCO device (LPC bus). > > Does it look correct? > > Yeah, it looks OK to me. Note there are changes queued up in Lee Jones' > tree for changing the lpc_ich_info into itco_wdt_platform_data. > > Btw, is there a reason that intel_pmc_ipc doesn't use the mfd_* API > since it's concerned with multiple functions? > Qipeng? > I saw the v2 come in, but didn't see this question addressed in the changelog. When design P-unit driver, we got feedback from BIOS that there will allocate a dedicate ACPI id for P-unit controller, and finally BIOS decide not do that, just put some necessary Resource in PMC acpi table. After that, we got request to do same thing for iTco. I agree it's better to update pmc driver to use mfd_add_devices to create punit and iTco device. -- Darren Hart Intel Open Source Technology Center -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Aug 26, 2015 at 08:22:33AM +0000, Zha, Qipeng wrote: > On Tue, Aug 18, 2015 at 04:50:56PM +0100, Matt Fleming wrote: > > On Mon, 2015-08-10 at 16:04 +0100, Shevchenko, Andriy wrote: > > > > > > Matt, by the way intel_pmc_ipc.c module creates iTCO device (LPC bus). > > > Does it look correct? > > > > Yeah, it looks OK to me. Note there are changes queued up in Lee Jones' > > tree for changing the lpc_ich_info into itco_wdt_platform_data. > > > > Btw, is there a reason that intel_pmc_ipc doesn't use the mfd_* API > > since it's concerned with multiple functions? > > > Qipeng? > > > I saw the v2 come in, but didn't see this question addressed in the changelog. > > When design P-unit driver, we got feedback from BIOS that there will allocate a dedicate > ACPI id for P-unit controller, and finally BIOS decide not do that, just put some necessary > Resource in PMC acpi table. > After that, we got request to do same thing for iTco. > > I agree it's better to update pmc driver to use mfd_add_devices to create punit and iTco device. Does this mean there sill be a v4 I should be waiting for?
diff --git a/arch/x86/include/asm/intel_punit_ipc.h b/arch/x86/include/asm/intel_punit_ipc.h new file mode 100644 index 0000000..08e3e14 --- /dev/null +++ b/arch/x86/include/asm/intel_punit_ipc.h @@ -0,0 +1,101 @@ +#ifndef _ASM_X86_INTEL_PUNIT_IPC_H_ +#define _ASM_X86_INTEL_PUNIT_IPC_H_ + +/* Commands supported on GLM core, are handled by different bars, + * unify these commands together here + */ +#define IPC_BIOS_PUNIT_CMD_BASE 0x00 +#define IPC_GTD_PUNIT_CMD_BASE 0x20 +#define IPC_ISPD_PUNIT_CMD_BASE 0x40 + +/* BIOS => Pcode commands */ +#define IPC_BIOS_PUNIT_CMD_ZERO (IPC_BIOS_PUNIT_CMD_BASE + 0x00) +#define IPC_BIOS_PUNIT_CMD_VR_INTERFACE (IPC_BIOS_PUNIT_CMD_BASE + 0x01) +#define IPC_BIOS_PUNIT_CMD_READ_PCS (IPC_BIOS_PUNIT_CMD_BASE + 0x02) +#define IPC_BIOS_PUNIT_CMD_WRITE_PCS (IPC_BIOS_PUNIT_CMD_BASE + 0x03) +#define IPC_BIOS_PUNIT_CMD_READ_PCU_CONFIG (IPC_BIOS_PUNIT_CMD_BASE + 0x04) +#define IPC_BIOS_PUNIT_CMD_WRITE_PCU_CONFIG (IPC_BIOS_PUNIT_CMD_BASE + 0x05) +#define IPC_BIOS_PUNIT_CMD_READ_PL1_SETTING (IPC_BIOS_PUNIT_CMD_BASE + 0x06) +#define IPC_BIOS_PUNIT_CMD_WRITE_PL1_SETTING (IPC_BIOS_PUNIT_CMD_BASE + 0x07) +#define IPC_BIOS_PUNIT_CMD_TRIGGER_VDD_RAM (IPC_BIOS_PUNIT_CMD_BASE + 0x08) +#define IPC_BIOS_PUNIT_CMD_READ_TELE_INFO (IPC_BIOS_PUNIT_CMD_BASE + 0x09) +#define IPC_BIOS_PUNIT_CMD_READ_TELE_TRACE_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x0a) +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_TRACE_CTRL \ + (IPC_BIOS_PUNIT_CMD_BASE + 0x0b) +#define IPC_BIOS_PUNIT_CMD_READ_TELE_EVENT_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x0c) +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_EVENT_CTRL \ + (IPC_BIOS_PUNIT_CMD_BASE + 0x0d) +#define IPC_BIOS_PUNIT_CMD_READ_TELE_TRACE (IPC_BIOS_PUNIT_CMD_BASE + 0x0e) +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_TRACE (IPC_BIOS_PUNIT_CMD_BASE + 0x0f) +#define IPC_BIOS_PUNIT_CMD_READ_TELE_EVENT (IPC_BIOS_PUNIT_CMD_BASE + 0x10) +#define IPC_BIOS_PUNIT_CMD_WRITE_TELE_EVENT (IPC_BIOS_PUNIT_CMD_BASE + 0x11) +#define IPC_BIOS_PUNIT_CMD_READ_MODULE_TEMP (IPC_BIOS_PUNIT_CMD_BASE + 0x12) +#define IPC_BIOS_PUNIT_CMD_RESERVED (IPC_BIOS_PUNIT_CMD_BASE + 0x13) +#define IPC_BIOS_PUNIT_CMD_READ_VOLTAGE_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x14) +#define IPC_BIOS_PUNIT_CMD_WRITE_VOLTAGE_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x15) +#define IPC_BIOS_PUNIT_CMD_READ_RATIO_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x16) +#define IPC_BIOS_PUNIT_CMD_WRITE_RATIO_OVER (IPC_BIOS_PUNIT_CMD_BASE + 0x17) +#define IPC_BIOS_PUNIT_CMD_READ_VF_GL_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x18) +#define IPC_BIOS_PUNIT_CMD_WRITE_VF_GL_CTRL (IPC_BIOS_PUNIT_CMD_BASE + 0x19) +#define IPC_BIOS_PUNIT_CMD_READ_FM_SOC_TEMP_THRESH \ + (IPC_BIOS_PUNIT_CMD_BASE + 0x1a) +#define IPC_BIOS_PUNIT_CMD_WRITE_FM_SOC_TEMP_THRESH \ + (IPC_BIOS_PUNIT_CMD_BASE + 0x1b) + +/*GT Driver => Pcode commands*/ +#define IPC_GTD_PUNIT_CMD_ZERO (IPC_GTD_PUNIT_CMD_BASE + 0x00) +#define IPC_GTD_PUNIT_CMD_CONFIG (IPC_GTD_PUNIT_CMD_BASE + 0x01) +#define IPC_GTD_PUNIT_CMD_READ_ICCP_LIC_CDYN_SCAL \ + (IPC_GTD_PUNIT_CMD_BASE + 0x02) +#define IPC_GTD_PUNIT_CMD_WRITE_ICCP_LIC_CDYN_SCAL \ + (IPC_GTD_PUNIT_CMD_BASE + 0x03) +#define IPC_GTD_PUNIT_CMD_GET_WM_VAL (IPC_GTD_PUNIT_CMD_BASE + 0x06) +#define IPC_GTD_PUNIT_CMD_WRITE_CONFIG_WISHREQ (IPC_GTD_PUNIT_CMD_BASE + 0x07) +#define IPC_GTD_PUNIT_CMD_READ_REQ_DUTY_CYCLE (IPC_GTD_PUNIT_CMD_BASE + 0x16) +#define IPC_GTD_PUNIT_CMD_DIS_VOL_FREQ_CHANGE_REQUEST \ + (IPC_GTD_PUNIT_CMD_BASE + 0x17) +#define IPC_GTD_PUNIT_CMD_DYNA_DUTY_CYCLE_CTRL (IPC_GTD_PUNIT_CMD_BASE + 0x1a) +#define IPC_GTD_PUNIT_CMD_DYNA_DUTY_CYCLE_TUNING \ + (IPC_GTD_PUNIT_CMD_BASE + 0x1c) + +/* ISP Driver => Pcode commands */ +#define IPC_ISPD_PUNIT_CMD_ZERO (IPC_ISPD_PUNIT_CMD_BASE + 0x00) +#define IPC_ISPD_PUNIT_CMD_CONFIG (IPC_ISPD_PUNIT_CMD_BASE + 0x01) +#define IPC_ISPD_PUNIT_CMD_GET_ISP_LTR_VAL (IPC_ISPD_PUNIT_CMD_BASE + 0x02) +#define IPC_ISPD_PUNIT_CMD_ACCESS_IU_FREQ_BOUNDS \ + (IPC_ISPD_PUNIT_CMD_BASE + 0x03) +#define IPC_ISPD_PUNIT_CMD_READ_CDYN_LEVEL (IPC_ISPD_PUNIT_CMD_BASE + 0x04) +#define IPC_ISPD_PUNIT_CMD_WRITE_CDYN_LEVEL (IPC_ISPD_PUNIT_CMD_BASE + 0x05) +#define IPC_ISPD_PUNIT_CMD_MAX (IPC_ISPD_PUNIT_CMD_BASE + 0x06) + +/* Error codes */ +#define IPC_ERR_SUCCESS 0 +#define IPC_ERR_INVALID_CMD 1 +#define IPC_ERR_INVALID_PARAMETER 2 +#define IPC_ERR_CMD_TIMEOUT 3 +#define IPC_ERR_CMD_LOCKED 4 +#define IPC_ERR_INVALID_VR_ID 5 +#define IPC_ERR_VR_ERR 6 + +#if IS_ENABLED(CONFIG_INTEL_PUNIT_IPC) + +int intel_punit_ipc_simple_command(int cmd, int para1, int para2); +int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out); + +#else + +static intline int intel_punit_ipc_simple_command(int cmd, + int para1, int para2); +{ + return -EINVAL; +} + +static inline int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, + u32 *in, u32 *out); +{ + return -EINVAL; +} + +#endif /*CONFIG_INTEL_PUNIT_IPC*/ + +#endif diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 346f1fd..42ada9b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -891,4 +891,10 @@ config INTEL_PMC_IPC The PMC is an ARC processor which defines IPC commands for communication with other entities in the CPU. +config INTEL_PUNIT_IPC + tristate "Intel PUNIT IPC Driver" + default y + ---help--- + IPC is used to bridge the communications between kernel and PUNIT + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 1051372..eea765f 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o +obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c new file mode 100644 index 0000000..78cb794 --- /dev/null +++ b/drivers/platform/x86/intel_punit_ipc.c @@ -0,0 +1,388 @@ +/* + * intel_punit_ipc.c: Driver for the Intel Punit Mailbox IPC mechanism + * + * (C) Copyright 2015 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The heart of the Punit is the Foxton microcontroller and its firmware, + * which provide mailbox interface for power management usage. + */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/pm.h> +#include <linux/acpi.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/atomic.h> +#include <linux/notifier.h> +#include <linux/suspend.h> +#include <linux/platform_device.h> +#include <asm/intel_punit_ipc.h> + +/* Mailbox registers */ +#define MAILBOX_DATA_LOW 0x0 +#define MAILBOX_INTERFACE 0x4 +#define CMD_RUN (1 << 31) +#define CMD_ERRCODE_MASK 0xFF +#define CMD_PARA1_SHIFT 8 +#define CMD_PARA2_SHIFT 16 +#define CMD_MASK 0xFF +#define MAILBOX_DATA_HIGH 0x8 + +#define MAILBOX_REGISTER_SPACE 0x10 + +#define CMD_TIMEOUT_SECONDS 3 + +/* Three external mailbox */ +enum mailbox_type { + BIOS_MAILBOX, + GTDRIVER_MAILBOX, + ISPDRIVER_MAILBOX, + RESERVED_MAILBOX, +}; + +struct intel_punit_ipc_controller { + struct platform_device *pdev; + struct mutex lock; + void __iomem *base[RESERVED_MAILBOX]; + struct completion cmd_complete; + int irq; + + int cmd; + enum mailbox_type type; +}; + +static char *ipc_err_sources[] = { + [IPC_ERR_SUCCESS] = + "no error", + [IPC_ERR_INVALID_CMD] = + "invalid command", + [IPC_ERR_INVALID_PARAMETER] = + "invalid parameter", + [IPC_ERR_CMD_TIMEOUT] = + "command timeout", + [IPC_ERR_CMD_LOCKED] = + "command locked", + [IPC_ERR_INVALID_VR_ID] = + "invalid vr id", + [IPC_ERR_VR_ERR] = + "vr error", +}; + +static struct intel_punit_ipc_controller ipcdev; + +static inline u32 ipc_read_status(void) +{ + return readl(ipcdev.base[ipcdev.type] + MAILBOX_INTERFACE); +} + +static inline void ipc_write_cmd(u32 cmd) +{ + writel(cmd, ipcdev.base[ipcdev.type] + MAILBOX_INTERFACE); +} + +static inline u32 ipc_read_data_low(void) +{ + return readl(ipcdev.base[ipcdev.type] + MAILBOX_DATA_LOW); +} + +static inline u32 ipc_read_data_high(void) +{ + return readl(ipcdev.base[ipcdev.type] + MAILBOX_DATA_HIGH); +} + +static inline void ipc_write_data_low(u32 data) +{ + writel(data, ipcdev.base[ipcdev.type] + MAILBOX_DATA_LOW); +} + +static inline void ipc_write_data_high(u32 data) +{ + writel(data, ipcdev.base[ipcdev.type] + MAILBOX_DATA_HIGH); +} + +static int intel_punit_init_cmd(u32 cmd) +{ + cmd &= CMD_MASK; + if (cmd < IPC_BIOS_PUNIT_CMD_BASE) + return -EINVAL; + else if (cmd < IPC_GTD_PUNIT_CMD_BASE) + ipcdev.type = BIOS_MAILBOX; + else if (cmd < IPC_ISPD_PUNIT_CMD_BASE) + ipcdev.type = GTDRIVER_MAILBOX; + else if (cmd < IPC_ISPD_PUNIT_CMD_MAX) + ipcdev.type = ISPDRIVER_MAILBOX; + else + return -EINVAL; + + return 0; +} + +static int intel_punit_ipc_send_command(u32 cmd) +{ + int ret; + + ret = intel_punit_init_cmd(cmd); + if (ret) + return ret; + ipcdev.cmd = cmd; + reinit_completion(&ipcdev.cmd_complete); + ipc_write_cmd(cmd); + return 0; +} + +static int intel_punit_ipc_check_status(void) +{ + int loops = CMD_TIMEOUT_SECONDS * USEC_PER_SEC; + int ret = 0; + int status; + int errcode; + + if (ipcdev.irq) { + if (0 == wait_for_completion_timeout( + &ipcdev.cmd_complete, + CMD_TIMEOUT_SECONDS * HZ)) { + dev_err(&ipcdev.pdev->dev, + "IPC timed out, IPC_CMD=0x%x\n", ipcdev.cmd); + return -ETIMEDOUT; + } + } else { + while ((ipc_read_status() & CMD_RUN) && --loops) + udelay(1); + if (!loops) { + dev_err(&ipcdev.pdev->dev, + "IPC timed out, IPC_CMD=0x%x\n", ipcdev.cmd); + return -ETIMEDOUT; + } + } + + status = ipc_read_status(); + errcode = status & CMD_ERRCODE_MASK; + if (errcode) { + ret = -EIO; + if (errcode < ARRAY_SIZE(ipc_err_sources)) + dev_err(&ipcdev.pdev->dev, + "IPC failed: %s, IPC_STS=0x%x, IPC_CMD=0x%x\n", + ipc_err_sources[errcode], status, ipcdev.cmd); + else + dev_err(&ipcdev.pdev->dev, + "IPC failed: unknown err,STS=0x%x, CMD=0x%x\n", + status, ipcdev.cmd); + } + + return ret; +} + +/** + * intel_punit_ipc_simple_command() - Simple IPC command + * @cmd: IPC command code. + * @para1: First 8bit parameter, set 0 if invalid. + * @para2: Second 8bit parameter, set 0 if invalid. + * + * Send a IPC command to Punit when there is no data transaction + * + * Return: an IPC error code or 0 on success. + */ +int intel_punit_ipc_simple_command(int cmd, int para1, int para2) +{ + int ret; + + mutex_lock(&ipcdev.lock); + ret = intel_punit_ipc_send_command(CMD_RUN | + para2 << CMD_PARA2_SHIFT | + para1 << CMD_PARA1_SHIFT | cmd); + if (ret) + goto out; + ret = intel_punit_ipc_check_status(); +out: + mutex_unlock(&ipcdev.lock); + return ret; +} +EXPORT_SYMBOL(intel_punit_ipc_simple_command); + +/** + * intel_punit_ipc_command() - IPC command with data and pointers + * @cmd: IPC command code. + * @para1: First 8bit parameter, set 0 if invalid. + * @para2: Second 8bit parameter, set 0 if invalid. + * @in: Input data, 32bit for BIOS cmd, two 32bit for GTD and ISPD. + * @out: Output data. + * + * Send a IPC command to Punit with data transaction + * + * Return: an IPC error code or 0 on success. + */ +int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out) +{ + int ret; + + mutex_lock(&ipcdev.lock); + ipc_write_data_low(*in); + if (ipcdev.type == GTDRIVER_MAILBOX || + ipcdev.type == ISPDRIVER_MAILBOX) { + in++; + ipc_write_data_high(*in); + } + ret = intel_punit_ipc_send_command(CMD_RUN | + para2 << CMD_PARA2_SHIFT | + para1 << CMD_PARA1_SHIFT | cmd); + if (ret) + goto out; + ret = intel_punit_ipc_check_status(); + *out = ipc_read_data_low(); + if (ipcdev.type == GTDRIVER_MAILBOX || + ipcdev.type == ISPDRIVER_MAILBOX) { + out++; + *out = ipc_read_data_high(); + } +out: + mutex_unlock(&ipcdev.lock); + return ret; +} +EXPORT_SYMBOL_GPL(intel_punit_ipc_command); + +static irqreturn_t intel_punit_ioc(int irq, void *dev_id) +{ + complete(&ipcdev.cmd_complete); + return IRQ_HANDLED; +} + +static int intel_punit_get_bars(struct platform_device *pdev) +{ + struct resource *res0, *res1; + void __iomem *addr; + int size; + int ret; + + res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res0) { + dev_err(&pdev->dev, "Failed to get iomem resource\n"); + return -EINVAL; + } + size = resource_size(res0); + if (!request_mem_region(res0->start, size, pdev->name)) { + dev_err(&pdev->dev, "Failed to request iomem resouce\n"); + return -EBUSY; + } + + res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res1) { + dev_err(&pdev->dev, "Failed to get iomem resource1\n"); + return -EINVAL; + } + size = resource_size(res1); + if (!request_mem_region(res1->start, size, pdev->name)) { + dev_err(&pdev->dev, "Failed to request iomem resouce1\n"); + ret = -EBUSY; + goto err_res1; + } + + addr = ioremap_nocache(res0->start, + resource_size(res0) + resource_size(res1)); + if (!addr) { + dev_err(&pdev->dev, "Failed to ioremap ipc base\n"); + ret = -ENOMEM; + goto err_map; + } + ipcdev.base[BIOS_MAILBOX] = addr; + addr += MAILBOX_REGISTER_SPACE; + ipcdev.base[GTDRIVER_MAILBOX] = addr; + addr += MAILBOX_REGISTER_SPACE; + ipcdev.base[ISPDRIVER_MAILBOX] = addr; + + return 0; + +err_map: + release_mem_region(res1->start, resource_size(res1)); +err_res1: + release_mem_region(res0->start, resource_size(res0)); + return ret; +} + +static int intel_punit_ipc_probe(struct platform_device *pdev) +{ + int irq; + int ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ipcdev.irq = 0; + dev_warn(&pdev->dev, "Could not get irq number\n"); + } else { + if (request_irq(irq, intel_punit_ioc, IRQF_NO_SUSPEND, + "intel_punit_ipc", &ipcdev)) { + dev_err(&pdev->dev, "request irq %d\n", irq); + return -EBUSY; + } + ipcdev.irq = irq; + } + + ret = intel_punit_get_bars(pdev); + if (ret) { + if (ipcdev.irq) + free_irq(ipcdev.irq, &ipcdev); + return ret; + } + + ipcdev.pdev = pdev; + mutex_init(&ipcdev.lock); + init_completion(&ipcdev.cmd_complete); + return ret; +} + +static int intel_punit_ipc_remove(struct platform_device *pdev) +{ + struct resource *res; + + if (ipcdev.irq) + free_irq(ipcdev.irq, &ipcdev); + iounmap(ipcdev.base[BIOS_MAILBOX]); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) + release_mem_region(res->start, resource_size(res)); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) + release_mem_region(res->start, resource_size(res)); + return 0; +} + +#ifdef CONFIG_ACPI +static const struct acpi_device_id punit_ipc_acpi_ids[] = { + {"INT34D4", 0} +}; +#endif + +static struct platform_driver intel_punit_ipc_driver = { + .probe = intel_punit_ipc_probe, + .remove = intel_punit_ipc_remove, + .driver = { + .name = "intel_punit_ipc", + .acpi_match_table = ACPI_PTR(punit_ipc_acpi_ids), + }, +}; + +static int __init intel_punit_ipc_init(void) +{ + return platform_driver_register(&intel_punit_ipc_driver); +} + +static void __exit intel_punit_ipc_exit(void) +{ + platform_driver_unregister(&intel_punit_ipc_driver); +} + +MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>"); +MODULE_DESCRIPTION("Intel Punit IPC driver"); +MODULE_LICENSE("GPL"); + +/* Some modules are dependent on this, so init earlier */ +fs_initcall(intel_punit_ipc_init); +module_exit(intel_punit_ipc_exit);
This driver provides support for Punit mailbox IPC on Intel platforms. The heart of the Punit is the Foxton microcontroller and its firmware, which provide mailbox interface for power management usage. Signed-off-by: Qipeng Zha <qipeng.zha@intel.com> --- arch/x86/include/asm/intel_punit_ipc.h | 101 +++++++++ drivers/platform/x86/Kconfig | 6 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel_punit_ipc.c | 388 +++++++++++++++++++++++++++++++++ 4 files changed, 496 insertions(+) create mode 100644 arch/x86/include/asm/intel_punit_ipc.h create mode 100644 drivers/platform/x86/intel_punit_ipc.c