From patchwork Thu May 23 13:49:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Madhvapathi Sriram X-Patchwork-Id: 2607031 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id 9F83E3FDBC for ; Thu, 23 May 2013 13:49:52 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UfVtu-0002Ma-JN; Thu, 23 May 2013 13:49:50 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UfVtr-0005Xn-PY; Thu, 23 May 2013 13:49:47 +0000 Received: from cluster-d.mailcontrol.com ([85.115.60.190]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UfVto-0005Wl-C4 for linux-arm-kernel@lists.infradead.org; Thu, 23 May 2013 13:49:46 +0000 Received: from SJOAMSEXC01.AMERICAS.ROOT.PRI (nse-zco.zoran.com [67.98.200.2]) by rly04d.srv.mailcontrol.com (MailControl) with ESMTP id r4NDnEHe029159 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL); Thu, 23 May 2013 14:49:15 +0100 Received: from BANASIEXC01.ASIA.ROOT.PRI (10.190.12.21) by SJOAMSEXC01.AMERICAS.ROOT.PRI (10.110.12.85) with Microsoft SMTP Server (TLS) id 14.2.318.1; Thu, 23 May 2013 06:49:13 -0700 Received: from BANASIEXM01.ASIA.ROOT.PRI ([10.190.12.23]) by banasiexc01.ASIA.ROOT.PRI ([10.190.12.21]) with mapi id 14.02.0318.001; Thu, 23 May 2013 19:19:10 +0530 From: Madhvapathi Sriram To: Barry Song <21cnbao@gmail.com>, "dtor@mail.ru" , "dmitry.torokhov@gmail.com" Subject: RE: [PATCH] input: sirfsoc_pwrc: add onkey input driver for CSR SiRFprimaII PWRC Thread-Topic: [PATCH] input: sirfsoc_pwrc: add onkey input driver for CSR SiRFprimaII PWRC Thread-Index: AQHOVwdS+/PQXfyj4E6x7vgrpWGA35kSwLBz Date: Thu, 23 May 2013 13:49:10 +0000 Message-ID: References: <1369239198-11059-1-git-send-email-Baohua.Song@csr.com> In-Reply-To: <1369239198-11059-1-git-send-email-Baohua.Song@csr.com> Accept-Language: en-US, en-GB Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.190.0.14] MIME-Version: 1.0 X-Scanned-By: MailControl 16089.0 (www.mailcontrol.com) on 10.68.0.114 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130523_094944_727124_83FDCE20 X-CRM114-Status: GOOD ( 23.86 ) 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 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [85.115.60.190 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Xianglong Du , DL-SHA-WorkGroupLinux , Binghua Duan , "linux-arm-kernel@lists.infradead.org" , "linux-input@vger.kernel.org" , Barry Song X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Comments inline. diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index bb698e1..1d91d1b 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -637,4 +637,14 @@ config INPUT_XEN_KBDDEV_FRONTEND To compile this driver as a module, choose M here: the module will be called xen-kbdfront. +config INPUT_SIRFSOC_ONKEY + bool "CSR SiRFSoC power on/off/suspend key support" + depends on ARCH_SIRF + default y + help + Say Y here if you want to support for the SiRFSoC power on/off/suspend key + in Linux, after you press the onkey, system will suspend. + + If unsure, say N. + endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index d7fc17f..1d66f03 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o +obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc_onkey.o diff --git a/drivers/input/misc/sirfsoc_onkey.c b/drivers/input/misc/sirfsoc_onkey.c new file mode 100644 index 0000000..3e48db9 --- /dev/null +++ b/drivers/input/misc/sirfsoc_onkey.c @@ -0,0 +1,176 @@ +/* + * Power key driver for SiRF PrimaII + * + * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sirfsoc_pwrc_drvdata { + u32 pwrc_base; + int irq; + struct input_dev *input; +}; + +#define PWRC_ON_KEY_BIT (1 << 0) + +#define PWRC_INT_STATUS 0xc +#define PWRC_INT_MASK 0x10 + +static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) +{ + struct sirfsoc_pwrc_drvdata *pwrcdrv = + (struct sirfsoc_pwrc_drvdata *)dev_id; + u32 int_status; + int_status = sirfsoc_rtc_iobrg_readl( + pwrcdrv->pwrc_base + PWRC_INT_STATUS); + sirfsoc_rtc_iobrg_writel(int_status & (~PWRC_ON_KEY_BIT), + pwrcdrv->pwrc_base + PWRC_INT_STATUS); + + /* + * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c + * to queue a SUSPEND APM event + */ + input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); + input_sync(pwrcdrv->input); + + /* + * Todo: report KEY_POWER event for Android platforms, Android PowerManager + * will handle the suspend and powerdown/hibernation + */ + + return IRQ_HANDLED; +} + +static const struct of_device_id sirfsoc_pwrc_of_match[] = { + { .compatible = "sirf,prima2-pwrc" }, + {}, +} +MODULE_DEVICE_TABLE(of, sirfsoc_pwrc_of_match); + +static int sirfsoc_pwrc_probe(struct platform_device *pdev) +{ + int ret; + struct sirfsoc_pwrc_drvdata *pwrcdrv = NULL; + struct device_node *np = pdev->dev.of_node; + + pwrcdrv = devm_kzalloc(&pdev->dev, + sizeof(struct sirfsoc_pwrc_drvdata), GFP_KERNEL); + if (!pwrcdrv) { + dev_info(&pdev->dev, "kzalloc fail!\n"); + return -ENOMEM; + } + + /* + * we can't use of_iomap because pwrc is not mapped in memory, the so-called base + * address is only offset in rtciobrg + */ + ret = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); Possible mem leak here - not freeing pwrcdrv + if (ret) { + dev_err(&pdev->dev, "unable to find base address of pwrc node in dtb\n"); + return ret; + } + + pwrcdrv->input = devm_input_allocate_device(&pdev->dev); + if (!pwrcdrv->input) + return -ENOMEM; + + pwrcdrv->input->name = "sirfsoc pwrckey"; + pwrcdrv->input->phys = "pwrc/input0"; + + platform_set_drvdata(pdev, pwrcdrv); + + pwrcdrv->irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(&pdev->dev, pwrcdrv->irq, + sirfsoc_pwrc_isr, IRQF_SHARED, + "sirfsoc_pwrc_int", pwrcdrv); + + sirfsoc_rtc_iobrg_writel( + sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) + | PWRC_ON_KEY_BIT, pwrcdrv->pwrc_base + PWRC_INT_MASK); Enabling the MASK for an interrupt should only come after it has been successfully claimed? Else we might be leaving and interrupt enabled without being able to handle it? Possible mem leak here not freeing any allocated devices/memory/irq. I suggest all the error handling be collated at the end of this function for various stages and error handling be done there. Please have a look at https://www.kernel.org/doc/Documentation/input/input-programming.txt + if (ret) { + dev_err(&pdev->dev, "pwrc: Unable to claim irq %d; error %d\n", + pwrcdrv->irq, ret); + return ret; + } + + pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR) | BIT_MASK(EV_KEY); + set_bit(KEY_POWER, pwrcdrv->input->keybit); + + ret = input_register_device(pwrcdrv->input); + if (ret) { + dev_err(&pdev->dev, + "pwrc: Unable to register input device,error: %d\n", + ret); + return ret; + } + + device_init_wakeup(&pdev->dev, 1); + + return 0; +} + +static int sirfsoc_pwrc_remove(struct platform_device *pdev) +{ + device_init_wakeup(&pdev->dev, 0); + + return 0; +} + +#ifdef CONFIG_PM +static int pwrc_suspend(struct device *dev) +{ + return 0; +} + +static int pwrc_resume(struct device *dev) +{ + struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev); + Typically, the wake up interrupts would be ensured to be active while going to sleep/suspend. However, here at resume the interrupt mask is being set. Is it because, there are some caveats here? + /* + * Do not mask pwrc interrupt as we want pwrc work as a wakeup source + * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c + */ + sirfsoc_rtc_iobrg_writel( + sirfsoc_rtc_iobrg_readl( + pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT, + pwrcdrv->pwrc_base + PWRC_INT_MASK); + + return 0; +} + +static const struct dev_pm_ops sirfsoc_pwrc_pm_ops = { + .suspend = pwrc_suspend, + .resume = pwrc_resume, +}; +#endif + +static struct platform_driver sirfsoc_pwrc_driver = { + .probe = sirfsoc_pwrc_probe, + .remove = sirfsoc_pwrc_remove, + .driver = { + .name = "sirfsoc-pwrc", + .owner = THIS_MODULE,