From patchwork Thu Jan 26 21:17:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 6416 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 0FA1A23E12 for ; Thu, 26 Jan 2012 21:17:25 +0000 (UTC) Received: from mail-bk0-f52.google.com (mail-bk0-f52.google.com [209.85.214.52]) by fiordland.canonical.com (Postfix) with ESMTP id E7518A184A1 for ; Thu, 26 Jan 2012 21:17:24 +0000 (UTC) Received: by bkar19 with SMTP id r19so1138267bka.11 for ; Thu, 26 Jan 2012 13:17:24 -0800 (PST) Received: by 10.204.10.82 with SMTP id o18mr1892132bko.20.1327612644597; Thu, 26 Jan 2012 13:17:24 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.204.130.220 with SMTP id u28cs52917bks; Thu, 26 Jan 2012 13:17:24 -0800 (PST) Received: by 10.14.15.208 with SMTP id f56mr1280469eef.41.1327612643371; Thu, 26 Jan 2012 13:17:23 -0800 (PST) Received: from eu1sys200aog104.obsmtp.com (eu1sys200aog104.obsmtp.com. [207.126.144.117]) by mx.google.com with SMTP id 23si3752859eej.180.2012.01.26.13.17.10 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 26 Jan 2012 13:17:23 -0800 (PST) Received-SPF: neutral (google.com: 207.126.144.117 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) client-ip=207.126.144.117; Authentication-Results: mx.google.com; spf=neutral (google.com: 207.126.144.117 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) smtp.mail=linus.walleij@stericsson.com Received: from beta.dmz-us.st.com ([167.4.1.35]) (using TLSv1) by eu1sys200aob104.postini.com ([207.126.147.11]) with SMTP ID DSNKTyHC1k1je5r3qodZxajbKt1BBTh+TMH/@postini.com; Thu, 26 Jan 2012 21:17:23 UTC Received: from zeta.dmz-us.st.com (ns4.st.com [167.4.16.71]) by beta.dmz-us.st.com (STMicroelectronics) with ESMTP id 2F3C23C; Thu, 26 Jan 2012 21:17:01 +0000 (GMT) Received: from relay2.stm.gmessaging.net (unknown [10.230.100.18]) by zeta.dmz-us.st.com (STMicroelectronics) with ESMTP id B020B45; Thu, 26 Jan 2012 20:15:35 +0000 (GMT) Received: from exdcvycastm003.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm003", Issuer "exdcvycastm003" (not verified)) by relay2.stm.gmessaging.net (Postfix) with ESMTPS id 27028A807B; Thu, 26 Jan 2012 22:17:00 +0100 (CET) Received: from steludxu4075.lud.stericsson.com (10.230.100.153) by smtp.stericsson.com (10.230.100.1) with Microsoft SMTP Server (TLS) id 8.3.83.0; Thu, 26 Jan 2012 22:17:07 +0100 From: Linus Walleij To: Samuel Ortiz , Cc: Viresh Kumar , Chris Blair , Linus Walleij Subject: [PATCH 1/2 v3] mfd/stmpe: Add support for no-interrupt config Date: Thu, 26 Jan 2012 22:17:03 +0100 Message-ID: <1327612623-9135-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.7.8 MIME-Version: 1.0 From: Chris Blair Adds support for boards which have an STMPE device without the interrupt pin connected. Acked-by: Viresh Kumar Signed-off-by: Chris Blair Tested-by: Michel Jaouen Reviewed-by: Srinidhi Kasagar Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - Corrects initialisation, error condition and driver removal cleanup for the no-irq configuration. ChangeLog v2->v3: - Removes the extra platform data member added to support no-irq mode and instead implements it using an invalid value for the existing irq member. This is propagated through to the sub-device drivers by having alternate versions of the cell data structures which do not have an irq resource defined. --- drivers/mfd/stmpe.c | 134 ++++++++++++++++++++++++++++++++------------- include/linux/mfd/stmpe.h | 1 + 2 files changed, 97 insertions(+), 38 deletions(-) diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index e07947e..2dd8d49 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -298,6 +298,11 @@ static struct mfd_cell stmpe_gpio_cell = { .num_resources = ARRAY_SIZE(stmpe_gpio_resources), }; +static struct mfd_cell stmpe_gpio_cell_noirq = { + .name = "stmpe-gpio", + /* gpio cell resources consist of an irq only so no resources here */ +}; + /* * Keypad (1601, 2401, 2403) */ @@ -346,6 +351,13 @@ static struct stmpe_variant_block stmpe801_blocks[] = { }, }; +static struct stmpe_variant_block stmpe801_blocks_noirq[] = { + { + .cell = &stmpe_gpio_cell_noirq, + .block = STMPE_BLOCK_GPIO, + }, +}; + static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks, bool enable) { @@ -367,6 +379,17 @@ static struct stmpe_variant_info stmpe801 = { .enable = stmpe801_enable, }; +static struct stmpe_variant_info stmpe801_noirq = { + .name = "stmpe801", + .id_val = STMPE801_ID, + .id_mask = 0xffff, + .num_gpios = 8, + .regs = stmpe801_regs, + .blocks = stmpe801_blocks_noirq, + .num_blocks = ARRAY_SIZE(stmpe801_blocks_noirq), + .enable = stmpe801_enable, +}; + /* * Touchscreen (STMPE811 or STMPE610) */ @@ -712,7 +735,7 @@ static struct stmpe_variant_info stmpe2403 = { .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ }; -static struct stmpe_variant_info *stmpe_variant_info[] = { +static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = { [STMPE610] = &stmpe610, [STMPE801] = &stmpe801, [STMPE811] = &stmpe811, @@ -721,6 +744,16 @@ static struct stmpe_variant_info *stmpe_variant_info[] = { [STMPE2403] = &stmpe2403, }; +/* + * These devices can be connected in a 'no-irq' configuration - the irq pin + * is not used and the device cannot interrupt the CPU. Here we only list + * devices which support this configuration - the driver will fail probing + * for any devices not listed here which are configured in this way. + */ +static struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = { + [STMPE801] = &stmpe801_noirq, +}; + static irqreturn_t stmpe_irq(int irq, void *data) { struct stmpe *stmpe = data; @@ -864,7 +897,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) unsigned int irq_trigger = stmpe->pdata->irq_trigger; int autosleep_timeout = stmpe->pdata->autosleep_timeout; struct stmpe_variant_info *variant = stmpe->variant; - u8 icr; + u8 icr = 0; unsigned int id; u8 data[2]; int ret; @@ -887,31 +920,33 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) if (ret) return ret; - if (id == STMPE801_ID) - icr = STMPE801_REG_SYS_CTRL_INT_EN; - else - icr = STMPE_ICR_LSB_GIM; - - /* STMPE801 doesn't support Edge interrupts */ - if (id != STMPE801_ID) { - if (irq_trigger == IRQF_TRIGGER_FALLING || - irq_trigger == IRQF_TRIGGER_RISING) - icr |= STMPE_ICR_LSB_EDGE; - } - - if (irq_trigger == IRQF_TRIGGER_RISING || - irq_trigger == IRQF_TRIGGER_HIGH) { + if (stmpe->irq >= 0) { if (id == STMPE801_ID) - icr |= STMPE801_REG_SYS_CTRL_INT_HI; + icr = STMPE801_REG_SYS_CTRL_INT_EN; else - icr |= STMPE_ICR_LSB_HIGH; - } + icr = STMPE_ICR_LSB_GIM; - if (stmpe->pdata->irq_invert_polarity) { - if (id == STMPE801_ID) - icr ^= STMPE801_REG_SYS_CTRL_INT_HI; - else - icr ^= STMPE_ICR_LSB_HIGH; + /* STMPE801 doesn't support Edge interrupts */ + if (id != STMPE801_ID) { + if (irq_trigger == IRQF_TRIGGER_FALLING || + irq_trigger == IRQF_TRIGGER_RISING) + icr |= STMPE_ICR_LSB_EDGE; + } + + if (irq_trigger == IRQF_TRIGGER_RISING || + irq_trigger == IRQF_TRIGGER_HIGH) { + if (id == STMPE801_ID) + icr |= STMPE801_REG_SYS_CTRL_INT_HI; + else + icr |= STMPE_ICR_LSB_HIGH; + } + + if (stmpe->pdata->irq_invert_polarity) { + if (id == STMPE801_ID) + icr ^= STMPE801_REG_SYS_CTRL_INT_HI; + else + icr ^= STMPE_ICR_LSB_HIGH; + } } if (stmpe->pdata->autosleep) { @@ -1001,19 +1036,38 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum) stmpe->irq = ci->irq; } + if (stmpe->irq < 0) { + /* use alternate variant info for no-irq mode, if supported */ + dev_info(stmpe->dev, + "%s configured in no-irq mode by platform data\n", + stmpe->variant->name); + if (!stmpe_noirq_variant_info[stmpe->partnum]) { + dev_err(stmpe->dev, + "%s does not support no-irq mode!\n", + stmpe->variant->name); + ret = -ENODEV; + goto free_gpio; + } + stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum]; + } + ret = stmpe_chip_init(stmpe); if (ret) goto free_gpio; - ret = stmpe_irq_init(stmpe); - if (ret) - goto free_gpio; + if (stmpe->irq >= 0) { + ret = stmpe_irq_init(stmpe); + if (ret) + goto free_gpio; - ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq, - pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe); - if (ret) { - dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret); - goto out_removeirq; + ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq, + pdata->irq_trigger | IRQF_ONESHOT, + "stmpe", stmpe); + if (ret) { + dev_err(stmpe->dev, "failed to request IRQ: %d\n", + ret); + goto out_removeirq; + } } ret = stmpe_devices_init(stmpe); @@ -1026,9 +1080,11 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum) out_removedevs: mfd_remove_devices(stmpe->dev); - free_irq(stmpe->irq, stmpe); + if (stmpe->irq >= 0) + free_irq(stmpe->irq, stmpe); out_removeirq: - stmpe_irq_remove(stmpe); + if (stmpe->irq >= 0) + stmpe_irq_remove(stmpe); free_gpio: if (pdata->irq_over_gpio) gpio_free(pdata->irq_gpio); @@ -1041,8 +1097,10 @@ int stmpe_remove(struct stmpe *stmpe) { mfd_remove_devices(stmpe->dev); - free_irq(stmpe->irq, stmpe); - stmpe_irq_remove(stmpe); + if (stmpe->irq >= 0) { + free_irq(stmpe->irq, stmpe); + stmpe_irq_remove(stmpe); + } if (stmpe->pdata->irq_over_gpio) gpio_free(stmpe->pdata->irq_gpio); @@ -1057,7 +1115,7 @@ static int stmpe_suspend(struct device *dev) { struct stmpe *stmpe = dev_get_drvdata(dev); - if (device_may_wakeup(dev)) + if (stmpe->irq >= 0 && device_may_wakeup(dev)) enable_irq_wake(stmpe->irq); return 0; @@ -1067,7 +1125,7 @@ static int stmpe_resume(struct device *dev) { struct stmpe *stmpe = dev_get_drvdata(dev); - if (device_may_wakeup(dev)) + if (stmpe->irq >= 0 && device_may_wakeup(dev)) disable_irq_wake(stmpe->irq); return 0; diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index ca1d7a3..a1c6aa7 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h @@ -26,6 +26,7 @@ enum stmpe_partnum { STMPE1601, STMPE2401, STMPE2403, + STMPE_NBR_PARTS }; /*