The power button is connected to MSIC on Medfield, we will get two interrupts from IOAPIC when pressing or releasing the power button.
Signed-off-by: Hong Liu <[email protected]> --- drivers/platform/x86/Kconfig | 9 ++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel_mid_powerbtn.c | 143 +++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 0 deletions(-) create mode 100644 drivers/platform/x86/intel_mid_powerbtn.c diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 4a15234..6dae7e9 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -561,4 +561,13 @@ config INTEL_MID_VIB If unsure, say N. +config INTEL_MID_POWER_BUTTON + tristate "power button driver for Intel MID platforms" + depends on INTEL_SCU_IPC + default y + help + This driver handles the power button on the Intel MID platforms. + + If unsure, say N. + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index ba295be..b0931e5 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -29,3 +29,4 @@ obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o obj-$(CONFIG_INTEL_SCU_IPC_UTIL)+= intel_scu_ipcutil.o obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o obj-$(CONFIG_INTEL_MID_VIB) += intel_mid_vibrator.o +obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c new file mode 100644 index 0000000..4f68f1d --- /dev/null +++ b/drivers/platform/x86/intel_mid_powerbtn.c @@ -0,0 +1,143 @@ +/* + * Power button driver for Medfield. + * + * Copyright (C) 2010 Intel Corp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <asm/intel_scu_ipc.h> + +#define DRIVER_NAME "msic_power_btn" + +#define MSIC_IRQ_STAT 0x02 + #define MSIC_IRQ_PB (1 << 0) +#define MSIC_PB_CONFIG 0x3e +#define MSIC_PB_STATUS 0x3f + #define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */ + +struct mfld_pb_priv { + struct input_dev *input; + int irq; +}; + +static irqreturn_t mfld_pb_isr(int irq, void *dev_id) +{ + struct mfld_pb_priv *priv = dev_id; + int ret; + u8 pbstat; + + ret = intel_scu_ipc_ioread8(MSIC_PB_STATUS, &pbstat); + if (ret < 0) + return IRQ_HANDLED; + + input_event(priv->input, EV_KEY, KEY_POWER, !(pbstat & MSIC_PB_LEVEL)); + input_sync(priv->input); + + return IRQ_HANDLED; +} + +static int __devinit mfld_pb_probe(struct platform_device *pdev) +{ + struct mfld_pb_priv *priv; + struct input_dev *input; + int ret; + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -EINVAL; + + priv = kzalloc(sizeof(struct mfld_pb_priv), GFP_KERNEL); + input = input_allocate_device(); + if (!priv || !input) { + ret = -ENOMEM; + goto fail; + } + + priv->input = input; + priv->irq = irq; + platform_set_drvdata(pdev, priv); + + input->name = pdev->name; + input->phys = "power-button/input0"; + input->dev.parent = &pdev->dev; + + input_set_capability(input, EV_KEY, KEY_POWER); + + ret = request_threaded_irq(priv->irq, NULL, mfld_pb_isr, + 0, DRIVER_NAME, priv); + if (ret) { + dev_err(&pdev->dev, + "unable to request irq %d for mfld power button\n",irq); + goto fail; + } + + ret = input_register_device(input); + if (ret) { + dev_err(&pdev->dev, + "unable to register input dev, error %d\n", ret); + goto fail; + } + return 0; + +fail: + platform_set_drvdata(pdev, NULL); + input_free_device(input); + kfree(priv); + return ret; +} + +static int __devexit mfld_pb_remove(struct platform_device *pdev) +{ + struct mfld_pb_priv *priv = platform_get_drvdata(pdev); + + free_irq(priv->irq, priv); + input_unregister_device(priv->input); + kfree(priv); + + return 0; +} + +static struct platform_driver mfld_pb_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = mfld_pb_probe, + .remove = __devexit_p(mfld_pb_remove), +}; + +static int __init mfld_pb_init(void) +{ + return platform_driver_register(&mfld_pb_driver); +} + +static void __exit mfld_pb_exit(void) +{ + platform_driver_unregister(&mfld_pb_driver); +} + +module_init(mfld_pb_init); +module_exit(mfld_pb_exit); + +MODULE_AUTHOR("Hong Liu <[email protected]>"); +MODULE_DESCRIPTION("Intel Medfield Power Button Driver"); +MODULE_LICENSE("GPL v2"); -- 1.7.3.2 _______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
