From patchwork Sun Dec 30 22:01:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Prisk X-Patchwork-Id: 1920151 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id CAB68DF23A for ; Sun, 30 Dec 2012 22:04:45 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TpQwM-0002Vp-DV; Sun, 30 Dec 2012 22:01:06 +0000 Received: from server.prisktech.co.nz ([115.188.14.127]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TpQwI-0002VH-N6 for linux-arm-kernel@lists.infradead.org; Sun, 30 Dec 2012 22:01:03 +0000 Received: from localhost.localdomain (unknown [192.168.0.102]) by server.prisktech.co.nz (Postfix) with ESMTP id 9088AFC0753; Mon, 31 Dec 2012 11:00:59 +1300 (NZDT) From: Tony Prisk To: Dmitry Torokhov , Dmity Torokhov Subject: [PATCH] input: vt8500: Add power button keypad driver Date: Mon, 31 Dec 2012 11:01:02 +1300 Message-Id: <1356904862-16417-1-git-send-email-linux@prisktech.co.nz> X-Mailer: git-send-email 1.7.9.5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121230_170103_394551_4A0D789A X-CRM114-Status: GOOD ( 24.15 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: vt8500-wm8505-linux-kernel@googlegroups.com, Tony Prisk , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-input@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch adds support for the Power Button keypad found on Wondermedia netbooks/tablets. A keymap property is exposed to allowing defining the key event to be generated when the power button is pressed. Signed-off-by: Tony Prisk --- .../bindings/input/vt8500-power-keypad.txt | 17 ++ drivers/input/keyboard/Kconfig | 10 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/wmt_power_keypad.c | 174 ++++++++++++++++++++ 4 files changed, 202 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/vt8500-power-keypad.txt create mode 100644 drivers/input/keyboard/wmt_power_keypad.c diff --git a/Documentation/devicetree/bindings/input/vt8500-power-keypad.txt b/Documentation/devicetree/bindings/input/vt8500-power-keypad.txt new file mode 100644 index 0000000..bae6228 --- /dev/null +++ b/Documentation/devicetree/bindings/input/vt8500-power-keypad.txt @@ -0,0 +1,17 @@ +* Wondermedia Power Keypad device tree bindings + +Wondermedia SoCs have a single irq-driven power button attached to +the power management controller. + +Required SoC Specific Properties: +- compatible: should be one of the following + - "wm,power-keypad": For all Wondermedia 8xxx-series SoCs. +- interrupts: should be the power management controller wakeup interrupt. +- keymap: linux keycode to generate when power button pressed. + +Example: + powerkey: pwrkey@0 { + compatible = "wm,power-keypad"; + interrupts = <22>; + keymap = <116>; /* KEY_POWER */ + }; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 5a240c6..c270f27 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -595,6 +595,16 @@ config KEYBOARD_TWL4030 To compile this driver as a module, choose M here: the module will be called twl4030_keypad. +config KEYBOARD_WMT_POWER_KEYPAD + tristate "Wondermedia Power keypad support" + depends on ARCH_VT8500 + help + Say Y here to enable support for the power button keypad + on Wondermedia 8xxx-series SoCs. + + To compile this driver as a module, choose M here: the + module will be called wmt_power_keypad. + config KEYBOARD_XTKBD tristate "XT keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 44e7600..eea31af 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -52,5 +52,6 @@ obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o +obj-$(CONFIG_KEYBOARD_WMT_POWER_KEYPAD) += wmt_power_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/wmt_power_keypad.c b/drivers/input/keyboard/wmt_power_keypad.c new file mode 100644 index 0000000..ce8aa9a --- /dev/null +++ b/drivers/input/keyboard/wmt_power_keypad.c @@ -0,0 +1,174 @@ +/* Wondermedia Power Keypad + * + * Copyright (C) 2012 Tony Prisk + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __iomem *pmc_base; +static struct input_dev *kpad_power; +static spinlock_t kpad_power_lock; +static int power_button_pressed; +static struct timer_list kpad_power_timer; +static unsigned int kpad_power_code; + +static inline void kpad_power_timeout(unsigned long fcontext) +{ + u32 status; + unsigned long flags; + + spin_lock_irqsave(&kpad_power_lock, flags); + + status = readl(pmc_base + 0x14); + + if (power_button_pressed) { + input_report_key(kpad_power, kpad_power_code, 0); + input_sync(kpad_power); + power_button_pressed = 0; + } + + spin_unlock_irqrestore(&kpad_power_lock, flags); +} + +static irqreturn_t kpad_power_isr(int irq_num, void *data) +{ + u32 status; + unsigned long flags; + + spin_lock_irqsave(&kpad_power_lock, flags); + + status = readl(pmc_base + 0x14); + udelay(100); + writel(status, pmc_base + 0x14); + + if (status & BIT(14)) { + if (!power_button_pressed) { + input_report_key(kpad_power, kpad_power_code, 1); + input_sync(kpad_power); + + power_button_pressed = 1; + + mod_timer(&kpad_power_timer, + jiffies + msecs_to_jiffies(500)); + } + } + + spin_unlock_irqrestore(&kpad_power_lock, flags); + + return IRQ_HANDLED; +} + +static int vt8500_pwr_kpad_probe(struct platform_device *pdev) +{ + struct device_node *np; + u32 status; + int err; + int irq; + + np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc"); + if (!np) { + dev_err(&pdev->dev, "pmc node not found\n"); + return -EINVAL; + } + + pmc_base = of_iomap(np, 0); + if (!pmc_base) { + dev_err(&pdev->dev, "unable to map pmc memory\n"); + return -ENOMEM; + } + + np = pdev->dev.of_node; + if (!np) { + dev_err(&pdev->dev, "devicenode not found\n"); + return -ENODEV; + } + + err = of_property_read_u32(np, "keymap", &kpad_power_code); + if (err) { + dev_warn(&pdev->dev, "defaulting to KEY_POWER\n"); + kpad_power_code = KEY_POWER; + } + + /* set power button to soft-power */ + status = readl(pmc_base + 0x54); + writel(status | 1, pmc_base + 0x54); + + /* clear any pending interrupts */ + status = readl(pmc_base + 0x14); + writel(status, pmc_base + 0x14); + + kpad_power = input_allocate_device(); + if (!kpad_power) { + dev_err(&pdev->dev, "failed to allocate input device\n"); + return -ENOMEM; + } + + spin_lock_init(&kpad_power_lock); + setup_timer(&kpad_power_timer, kpad_power_timeout, + (unsigned long)kpad_power); + + irq = irq_of_parse_and_map(np, 0); + err = request_irq(irq, &kpad_power_isr, 0, "pwrbtn", NULL); + if (err < 0) { + dev_err(&pdev->dev, "failed to request irq\n"); + return err; + } + + kpad_power->evbit[0] = BIT_MASK(EV_KEY); + set_bit(kpad_power_code, kpad_power->keybit); + + kpad_power->name = "wmt_power_keypad"; + kpad_power->phys = "wmt_power_keypad"; + kpad_power->keycode = &kpad_power_code; + kpad_power->keycodesize = sizeof(unsigned int); + kpad_power->keycodemax = 1; + + err = input_register_device(kpad_power); + if (err < 0) { + dev_err(&pdev->dev, "failed to register input device\n"); + return err; + } + + return 0; +} + +static struct of_device_id vt8500_pwr_kpad_dt_ids[] = { + { .compatible = "wm,power-keypad" }, + { /* Sentinel */ }, +}; + +static struct platform_driver vt8500_pwr_kpad_driver = { + .probe = vt8500_pwr_kpad_probe, + .driver = { + .name = "wmt-power-keypad", + .owner = THIS_MODULE, + .of_match_table = vt8500_pwr_kpad_dt_ids, + }, +}; + +module_platform_driver(vt8500_pwr_kpad_driver); + +MODULE_DESCRIPTION("Wondermedia Power Keypad Driver"); +MODULE_AUTHOR("Tony Prisk "); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, vt8500_pwr_kpad_dt_ids);