From patchwork Sat Jul 13 04:25:49 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Shiyan X-Patchwork-Id: 2827115 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B5D239F968 for ; Sat, 13 Jul 2013 04:26:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1F2C12012D for ; Sat, 13 Jul 2013 04:26:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C5EBB2012B for ; Sat, 13 Jul 2013 04:26:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750775Ab3GME0R (ORCPT ); Sat, 13 Jul 2013 00:26:17 -0400 Received: from smtp2.mail.ru ([94.100.176.130]:43962 "EHLO smtp2.mail.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750771Ab3GME0Q (ORCPT ); Sat, 13 Jul 2013 00:26:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail2; h=Message-Id:Date:Subject:Cc:To:From; bh=EDoc7DDuNjGqXmIs4Bkktpy5WPf24DQPjJzff75fKMk=; b=DP88r8qB3DXCTFyr21z3IrhrtsWub+z4OM6Bh2RpvWS/LoFcUJ1Pe93Mf+8rrROE4tWPn82mlTDYSDNtyVe7RyEQGiq/dcNv8hn8b9hEorM581p3fPqMuzyDY8KCTTwQzPx+n4lno+RrHXXIe+t7DdKE8Bko5Vo69OR59+XR3Ok=; Received: from [188.134.40.128] (port=30539 helo=shc.zet) by smtp2.mail.ru with esmtpa (envelope-from ) id 1UxrPR-00081b-FN; Sat, 13 Jul 2013 08:26:14 +0400 From: Alexander Shiyan To: linux-arm-kernel@lists.infradead.org Cc: linux-input@vger.kernel.org, Grant Likely , Rob Herring , Sascha Hauer , Dmitry Torokhov , Shawn Guo , Alexander Shiyan Subject: [PATCH v2 1/3] input: mc13783: Prepare driver to support MC13892 and OF Date: Sat, 13 Jul 2013 08:25:49 +0400 Message-Id: <1373689551-24375-1-git-send-email-shc_work@mail.ru> X-Mailer: git-send-email 1.8.1.5 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, FREEMAIL_FROM,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Mras: Ok Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-1.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RDNS_NONE, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch is a preparation mc13xxx powerbutton driver to support MC13892 and support the probe through the DT. Signed-off-by: Alexander Shiyan --- arch/arm/mach-imx/mach-mx31moboard.c | 9 +- drivers/input/misc/mc13783-pwrbutton.c | 361 ++++++++++++++------------------- include/linux/mfd/mc13xxx.h | 28 +-- 3 files changed, 173 insertions(+), 225 deletions(-) diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index 6f424ec..2a8aa43 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -276,9 +276,12 @@ static struct mc13xxx_leds_platform_data moboard_leds = { }; static struct mc13xxx_buttons_platform_data moboard_buttons = { - .b1on_flags = MC13783_BUTTON_DBNC_750MS | MC13783_BUTTON_ENABLE | - MC13783_BUTTON_POL_INVERT, - .b1on_key = KEY_POWER, + .buttons[0] = { + .keycode = KEY_POWER, + .flags = MC13XXX_BUTTON_ENABLE | + MC13XXX_BUTTON_DBNC_750MS | + MC13XXX_BUTTON_POL_INVERT, + }, }; static struct mc13xxx_codec_platform_data moboard_codec = { diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c index d0277a7..33613ca 100644 --- a/drivers/input/misc/mc13783-pwrbutton.c +++ b/drivers/input/misc/mc13783-pwrbutton.c @@ -24,248 +24,191 @@ #include #include #include -#include #include #include -#include -#include - -struct mc13783_pwrb { - struct input_dev *pwr; - struct mc13xxx *mc13783; -#define MC13783_PWRB_B1_POL_INVERT (1 << 0) -#define MC13783_PWRB_B2_POL_INVERT (1 << 1) -#define MC13783_PWRB_B3_POL_INVERT (1 << 2) - int flags; - unsigned short keymap[3]; + +struct mc13xxx_button_def { + unsigned int irq; + unsigned int sense_bit; }; -#define MC13783_REG_INTERRUPT_SENSE_1 5 -#define MC13783_IRQSENSE1_ONOFD1S (1 << 3) -#define MC13783_IRQSENSE1_ONOFD2S (1 << 4) -#define MC13783_IRQSENSE1_ONOFD3S (1 << 5) +struct mc13xxx_pwrb_devtype { + struct mc13xxx_button_def btn_def[MAX13XXX_NUM_BUTTONS]; +}; -#define MC13783_REG_POWER_CONTROL_2 15 -#define MC13783_POWER_CONTROL_2_ON1BDBNC 4 -#define MC13783_POWER_CONTROL_2_ON2BDBNC 6 -#define MC13783_POWER_CONTROL_2_ON3BDBNC 8 -#define MC13783_POWER_CONTROL_2_ON1BRSTEN (1 << 1) -#define MC13783_POWER_CONTROL_2_ON2BRSTEN (1 << 2) -#define MC13783_POWER_CONTROL_2_ON3BRSTEN (1 << 3) +struct mc13xxx_pwrb { + struct mc13xxx_pwrb_devtype *devtype; + unsigned int enabled; + unsigned int inverted; + u16 btn_code[MAX13XXX_NUM_BUTTONS]; + struct input_dev *input; + struct mc13xxx *mc13xxx; +}; -static irqreturn_t button_irq(int irq, void *_priv) -{ - struct mc13783_pwrb *priv = _priv; - int val; - - mc13xxx_irq_ack(priv->mc13783, irq); - mc13xxx_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_SENSE_1, &val); - - switch (irq) { - case MC13783_IRQ_ONOFD1: - val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0; - if (priv->flags & MC13783_PWRB_B1_POL_INVERT) - val ^= 1; - input_report_key(priv->pwr, priv->keymap[0], val); - break; - - case MC13783_IRQ_ONOFD2: - val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0; - if (priv->flags & MC13783_PWRB_B2_POL_INVERT) - val ^= 1; - input_report_key(priv->pwr, priv->keymap[1], val); - break; - - case MC13783_IRQ_ONOFD3: - val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0; - if (priv->flags & MC13783_PWRB_B3_POL_INVERT) - val ^= 1; - input_report_key(priv->pwr, priv->keymap[2], val); - break; - } +#define MC13XXX_REG_INTERRUPT_SENSE_1 5 +#define MC13XXX_REG_POWER_CONTROL_2 15 - input_sync(priv->pwr); +static irqreturn_t mc13xxx_pwrbutton_irq(int irq, void *data) +{ + struct mc13xxx_pwrb *priv = data; + unsigned int i, val; + + mc13xxx_irq_ack(priv->mc13xxx, irq); + mc13xxx_reg_read(priv->mc13xxx, MC13XXX_REG_INTERRUPT_SENSE_1, &val); + + for (i = 0; i < MAX13XXX_NUM_BUTTONS; i++) + if (irq == priv->devtype->btn_def[i].irq) { + val = !!(val & priv->devtype->btn_def[i].sense_bit); + if (priv->inverted & BIT(i)) + val = !val; + input_report_key(priv->input, priv->btn_code[i], val); + input_sync(priv->input); + break; + } return IRQ_HANDLED; } -static int mc13783_pwrbutton_probe(struct platform_device *pdev) +static int mc13xxx_pwrbutton_open(struct input_dev *dev) { - const struct mc13xxx_buttons_platform_data *pdata; - struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); - struct input_dev *pwr; - struct mc13783_pwrb *priv; - int err = 0; - int reg = 0; - - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - dev_err(&pdev->dev, "missing platform data\n"); - return -ENODEV; - } - - pwr = input_allocate_device(); - if (!pwr) { - dev_dbg(&pdev->dev, "Can't allocate power button\n"); - return -ENOMEM; - } - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - err = -ENOMEM; - dev_dbg(&pdev->dev, "Can't allocate power button\n"); - goto free_input_dev; - } - - reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC; - reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC; - reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC; - - priv->pwr = pwr; - priv->mc13783 = mc13783; - - mc13xxx_lock(mc13783); - - if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) { - priv->keymap[0] = pdata->b1on_key; - if (pdata->b1on_key != KEY_RESERVED) - __set_bit(pdata->b1on_key, pwr->keybit); - - if (pdata->b1on_flags & MC13783_BUTTON_POL_INVERT) - priv->flags |= MC13783_PWRB_B1_POL_INVERT; - - if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN) - reg |= MC13783_POWER_CONTROL_2_ON1BRSTEN; - - err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD1, - button_irq, "b1on", priv); - if (err) { - dev_dbg(&pdev->dev, "Can't request irq\n"); - goto free_priv; + struct mc13xxx_pwrb *priv = input_get_drvdata(dev); + int i, ret = 0; + + mc13xxx_lock(priv->mc13xxx); + + for (i = 0; i < MAX13XXX_NUM_BUTTONS; i++) + if (priv->enabled & BIT(i)) { + ret = mc13xxx_irq_request(priv->mc13xxx, + priv->devtype->btn_def[i].irq, + mc13xxx_pwrbutton_irq, NULL, + priv); + if (!ret) + continue; + + dev_err(&dev->dev, "Can't request IRQ: %i\n", ret); + + while (--i >= 0) + if (priv->enabled & BIT(i)) + mc13xxx_irq_free(priv->mc13xxx, + priv->devtype->btn_def[i].irq, + priv); + break; } - } - - if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) { - priv->keymap[1] = pdata->b2on_key; - if (pdata->b2on_key != KEY_RESERVED) - __set_bit(pdata->b2on_key, pwr->keybit); - if (pdata->b2on_flags & MC13783_BUTTON_POL_INVERT) - priv->flags |= MC13783_PWRB_B2_POL_INVERT; + mc13xxx_unlock(priv->mc13xxx); - if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN) - reg |= MC13783_POWER_CONTROL_2_ON2BRSTEN; - - err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD2, - button_irq, "b2on", priv); - if (err) { - dev_dbg(&pdev->dev, "Can't request irq\n"); - goto free_irq_b1; - } - } - - if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) { - priv->keymap[2] = pdata->b3on_key; - if (pdata->b3on_key != KEY_RESERVED) - __set_bit(pdata->b3on_key, pwr->keybit); + return ret; +} - if (pdata->b3on_flags & MC13783_BUTTON_POL_INVERT) - priv->flags |= MC13783_PWRB_B3_POL_INVERT; +static void mc13xxx_pwrbutton_close(struct input_dev *dev) +{ + struct mc13xxx_pwrb *priv = input_get_drvdata(dev); + int i; + + mc13xxx_lock(priv->mc13xxx); + for (i = 0; i < MAX13XXX_NUM_BUTTONS; i++) + if (priv->enabled & BIT(i)) + mc13xxx_irq_free(priv->mc13xxx, + priv->devtype->btn_def[i].irq, priv); + mc13xxx_unlock(priv->mc13xxx); +} - if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN) - reg |= MC13783_POWER_CONTROL_2_ON3BRSTEN; +static int __init mc13xxx_pwrbutton_probe(struct platform_device *pdev) +{ + struct mc13xxx_buttons_platform_data *pdata = + dev_get_platdata(&pdev->dev); + struct mc13xxx *mc13xxx = dev_get_drvdata(pdev->dev.parent); + struct mc13xxx_pwrb_devtype *devtype = + (struct mc13xxx_pwrb_devtype *)pdev->id_entry->driver_data; + struct mc13xxx_pwrb *priv; + int i, reg = 0, ret = -EINVAL; - err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD3, - button_irq, "b3on", priv); - if (err) { - dev_dbg(&pdev->dev, "Can't request irq: %d\n", err); - goto free_irq_b2; - } + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; } - mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg); - - mc13xxx_unlock(mc13783); - - pwr->name = "mc13783_pwrbutton"; - pwr->phys = "mc13783_pwrbutton/input0"; - pwr->dev.parent = &pdev->dev; - - pwr->keycode = priv->keymap; - pwr->keycodemax = ARRAY_SIZE(priv->keymap); - pwr->keycodesize = sizeof(priv->keymap[0]); - __set_bit(EV_KEY, pwr->evbit); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - err = input_register_device(pwr); - if (err) { - dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); - goto free_irq; - } + priv->input = devm_input_allocate_device(&pdev->dev); + if (!priv->input) + return -ENOMEM; + priv->mc13xxx = mc13xxx; + priv->devtype = devtype; platform_set_drvdata(pdev, priv); - return 0; - -free_irq: - mc13xxx_lock(mc13783); - - if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) - mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv); - -free_irq_b2: - if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) - mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv); - -free_irq_b1: - if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) - mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv); - -free_priv: - mc13xxx_unlock(mc13783); - kfree(priv); - -free_input_dev: - input_free_device(pwr); + for (i = 0; i < MAX13XXX_NUM_BUTTONS; i++) { + u16 code, invert, reset, debounce; + + if (!(pdata->buttons[i].flags & MC13XXX_BUTTON_ENABLE)) + continue; + code = pdata->buttons[i].keycode; + invert = !!(pdata->buttons[i].flags & + MC13XXX_BUTTON_POL_INVERT); + reset = !!(pdata->buttons[i].flags & + MC13XXX_BUTTON_RESET_EN); + debounce = pdata->buttons[i].flags; + + priv->btn_code[i] = code; + if (code != KEY_RESERVED) + __set_bit(code, priv->input->keybit); + + priv->enabled |= BIT(i); + priv->inverted |= invert << i; + reg |= reset << (i + 1); + reg |= (debounce & 0x03) << (4 + i * 2); + } - return err; + mc13xxx_lock(mc13xxx); + mc13xxx_reg_rmw(mc13xxx, MC13XXX_REG_POWER_CONTROL_2, 0x3fe, reg); + mc13xxx_unlock(mc13xxx); + + priv->input->name = "mc13xxx_pwrbutton"; + priv->input->phys = "mc13xxx_pwrbutton/input0"; + priv->input->id.bustype = BUS_HOST; + priv->input->id.vendor = 0x0001; + priv->input->id.product = 0x0001; + priv->input->id.version = 0x0100; + priv->input->keycode = priv->btn_code; + priv->input->keycodemax = ARRAY_SIZE(priv->btn_code); + priv->input->keycodesize = sizeof(priv->btn_code[0]); + priv->input->open = mc13xxx_pwrbutton_open; + priv->input->close = mc13xxx_pwrbutton_close; + __set_bit(EV_KEY, priv->input->evbit); + + input_set_drvdata(priv->input, priv); + + ret = input_register_device(priv->input); + if (ret) + dev_err(&pdev->dev, "Can't register input device: %i\n", ret); + + return ret; } -static int mc13783_pwrbutton_remove(struct platform_device *pdev) -{ - struct mc13783_pwrb *priv = platform_get_drvdata(pdev); - const struct mc13xxx_buttons_platform_data *pdata; - - pdata = dev_get_platdata(&pdev->dev); - - mc13xxx_lock(priv->mc13783); - - if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) - mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD3, priv); - if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) - mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD2, priv); - if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) - mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD1, priv); - - mc13xxx_unlock(priv->mc13783); - - input_unregister_device(priv->pwr); - kfree(priv); +static const struct mc13xxx_pwrb_devtype mc13783_pwrb_devtype = { + .btn_def[0] = { MC13783_IRQ_ONOFD1, BIT(3) }, + .btn_def[1] = { MC13783_IRQ_ONOFD2, BIT(4) }, + .btn_def[2] = { MC13783_IRQ_ONOFD3, BIT(5) } +}; - return 0; -} +static const struct platform_device_id mc13xxx_pwrbutton_id_table[] = { + { "mc13783-pwrbutton", (kernel_ulong_t)&mc13783_pwrb_devtype }, + { } +}; +MODULE_DEVICE_TABLE(platform, mc13xxx_pwrbutton_id_table); -static struct platform_driver mc13783_pwrbutton_driver = { - .probe = mc13783_pwrbutton_probe, - .remove = mc13783_pwrbutton_remove, - .driver = { - .name = "mc13783-pwrbutton", +static struct platform_driver mc13xxx_pwrbutton_driver = { + .driver = { + .name = "mc13xxx-pwrbutton", .owner = THIS_MODULE, }, + .id_table = mc13xxx_pwrbutton_id_table, }; +module_platform_driver_probe(mc13xxx_pwrbutton_driver, mc13xxx_pwrbutton_probe); -module_platform_driver(mc13783_pwrbutton_driver); - -MODULE_ALIAS("platform:mc13783-pwrbutton"); MODULE_DESCRIPTION("MC13783 Power Button"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Philippe Retornaz"); diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h index 41ed592..b895538 100644 --- a/include/linux/mfd/mc13xxx.h +++ b/include/linux/mfd/mc13xxx.h @@ -142,20 +142,22 @@ struct mc13xxx_leds_platform_data { u32 led_control[MAX_LED_CONTROL_REGS]; }; +#define MAX13XXX_NUM_BUTTONS 3 + +struct mc13xxx_button { + u16 keycode; + unsigned int flags; +#define MC13XXX_BUTTON_DBNC_0MS 0 +#define MC13XXX_BUTTON_DBNC_30MS 1 +#define MC13XXX_BUTTON_DBNC_150MS 2 +#define MC13XXX_BUTTON_DBNC_750MS 3 +#define MC13XXX_BUTTON_ENABLE (1 << 2) +#define MC13XXX_BUTTON_POL_INVERT (1 << 3) +#define MC13XXX_BUTTON_RESET_EN (1 << 4) +}; + struct mc13xxx_buttons_platform_data { -#define MC13783_BUTTON_DBNC_0MS 0 -#define MC13783_BUTTON_DBNC_30MS 1 -#define MC13783_BUTTON_DBNC_150MS 2 -#define MC13783_BUTTON_DBNC_750MS 3 -#define MC13783_BUTTON_ENABLE (1 << 2) -#define MC13783_BUTTON_POL_INVERT (1 << 3) -#define MC13783_BUTTON_RESET_EN (1 << 4) - int b1on_flags; - unsigned short b1on_key; - int b2on_flags; - unsigned short b2on_key; - int b3on_flags; - unsigned short b3on_key; + struct mc13xxx_button buttons[MAX13XXX_NUM_BUTTONS]; }; struct mc13xxx_ts_platform_data {