From patchwork Tue Oct 4 15:08:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 678144 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3spMkr0qxWz9svs for ; Wed, 5 Oct 2016 02:09:08 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b=Pllbhz6t; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753253AbcJDPJB (ORCPT ); Tue, 4 Oct 2016 11:09:01 -0400 Received: from mail-lf0-f45.google.com ([209.85.215.45]:34543 "EHLO mail-lf0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753788AbcJDPI7 (ORCPT ); Tue, 4 Oct 2016 11:08:59 -0400 Received: by mail-lf0-f45.google.com with SMTP id b81so67712136lfe.1 for ; Tue, 04 Oct 2016 08:08:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=aK00BcvbdDbnU/No+YflI0EVy8pBlzqntfrp3BV6XRc=; b=Pllbhz6toB7lh+SQBVvLgGhB185RLw1V5wcPL6KpA5u34/+7oqs4cCkoWZc6ewOJVW vbHkUTo2V4gA9lIDxuwR78M1PORWH/+FyGluVpfaN1VFFe3Wl61QmU63oF8rDJaAxmIO uIJrpViARiWPtt7cB8HLwY41Mfkm/7cNW4cXoyDzgbcXPMR0/j2ImF0o4PyJmJ+DTXgF FjoNBQnyrfcd9QMuQzM8V4RwZAIGDYH30E0jlMEa2fvHu+UnEtrRhTEYw8GxUT6ahBpt B4aOiju0KrPYFHtaM5o8z0YVkDvE01xasETD7JVPRpijbvxCpcan6lwwzp45nmzj/WEE aMkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=aK00BcvbdDbnU/No+YflI0EVy8pBlzqntfrp3BV6XRc=; b=nL1pIlSNS9YzL11K7juPCBFnW5AFMhiPj+hWtTrAPcPJggxmk9N9atW577WYaUm62t 7Z5Nf1mEK5gHD/3L0iFlU/lch6YUvRbbhV9ZQsDm85WvdNj1QVunhjSxD3ER/k4yKukS up98XL4Q5upi7066XJRbX/4thvvQJfdaa+mifRunBtP7sAHniqDvveZwbuPE0AQFo6pe eREOaTpR+PgqXTNEyoBiP3pzvyou9kPabtL2vAcUB2+cSFtUX1sTu4W77ksKd4iAhbdz lkcnuzUF0oohC6ZQlonuDYMJymDdRfaB1zj7LkDRVagVX/pr6MWhIxRx92sbGVyLu4bi RfAg== X-Gm-Message-State: AA6/9Rkd4vxgMFUbHiqOsToegThQkr7r8KOYUd8kGlbAV/5tqZrR+lXOJ3VJtQzEMZ04mW8c X-Received: by 10.194.206.68 with SMTP id lm4mr3406253wjc.106.1475593737648; Tue, 04 Oct 2016 08:08:57 -0700 (PDT) Received: from boomer.baylibre.com ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id j198sm4583539wmg.4.2016.10.04.08.08.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Oct 2016 08:08:57 -0700 (PDT) From: Jerome Brunet To: Kevin Hilman , Carlo Caione , Thomas Gleixner , Jason Cooper , Marc Zyngier Cc: Jerome Brunet , linux-amlogic@lists.infradead.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org Subject: [RFC 10/10] irqchip: meson: Add support for IRQ_TYPE_EDGE_BOTH Date: Tue, 4 Oct 2016 17:08:28 +0200 Message-Id: <1475593708-10526-11-git-send-email-jbrunet@baylibre.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1475593708-10526-1-git-send-email-jbrunet@baylibre.com> References: <1475593708-10526-1-git-send-email-jbrunet@baylibre.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The IP cannot take IRQ_EDGE_BOTH because the polarity in the filtering block is just one bit. It can trigger on either edge, but not both with the same configuration. This prevents meson based SoC to use some simple generic driver, like gpio-keys. The proposition is to change edge polarity in the end of interrupt callback (just toggling the polarity register of the IP). This works nicely but has 2 limitations: 1) If the signal is initially high, the first falling edge will not be detected, because the chip is initially configured for a rising edge. 2) If the signal changes too quickly for all edges to be properly handled, an additional edge might get lost, for the same reason as point 1. There is no drawback for introducing this work around so, knowing the limitation, it would be nice to have it Signed-off-by: Jerome Brunet --- drivers/irqchip/irq-meson-gpio.c | 45 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c index 184025a9cdaf..5bcbefef3e94 100644 --- a/drivers/irqchip/irq-meson-gpio.c +++ b/drivers/irqchip/irq-meson-gpio.c @@ -58,6 +58,7 @@ struct meson_gpio_irq_domain { struct meson_gpio_irq_chip { void __iomem *base; int index; + unsigned int flow_type; }; static const struct meson_gpio_irq_params meson8_params = { @@ -91,6 +92,19 @@ static void meson_gpio_irq_update_bits(void __iomem *base, unsigned int reg, writel(tmp, base + reg); } +static void meson_gpio_irq_flip_bits(void __iomem *base, unsigned int reg, + u32 mask) +{ + u32 tmp, val; + + tmp = readl(base + reg); + val = tmp ^ mask; + tmp = (tmp & val) | val; + + writel(tmp, base + reg); +} + + static int meson_gpio_irq_get_index(struct meson_gpio_irq_domain *domain_data, int hwirq) { @@ -135,11 +149,15 @@ static int meson_gpio_irq_set_type(struct irq_data *data, unsigned int type) pr_debug("set type of hwirq %lu to %u\n", data->hwirq, type); - if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) - return -EINVAL; + cd->flow_type = type; if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) val |= REG_EDGE_POL_EDGE(cd->index); + /* + * Take care of the dual polarity issue here, starting positive + */ + if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) + type &= ~IRQ_TYPE_EDGE_FALLING; if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) { val |= REG_EDGE_POL_LOW(cd->index); @@ -162,11 +180,31 @@ static int meson_gpio_irq_set_type(struct irq_data *data, unsigned int type) return irq_chip_set_type_parent(data, type); } +static void meson_gpio_irq_eoi(struct irq_data *data) +{ + struct meson_gpio_irq_chip *cd = irq_data_get_irq_chip_data(data); + + /* + * To simulate IRQ_TYPE_EDGE_BOTH, change the polarity of the edge + * after each interrupt. + * Limitation: + * 1) If the signal is initially high, the first falling edge will not + * be detected + * 2) If the signal changes too quickly to detect all the edges, an + * additional edge might get lost. + */ + if ((cd->flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) + meson_gpio_irq_flip_bits(cd->base, REG_EDGE_POL, + REG_EDGE_POL_LOW(cd->index)); + + irq_chip_eoi_parent(data); +} + static struct irq_chip meson_gpio_irq_chip = { .name = "meson-gpio-irqchip", .irq_mask = irq_chip_mask_parent, .irq_unmask = irq_chip_unmask_parent, - .irq_eoi = irq_chip_eoi_parent, + .irq_eoi = meson_gpio_irq_eoi, .irq_set_type = meson_gpio_irq_set_type, .irq_retrigger = irq_chip_retrigger_hierarchy, #ifdef CONFIG_SMP @@ -221,6 +259,7 @@ static int meson_gpio_irq_domain_alloc(struct irq_domain *domain, cd->base = domain_data->base; cd->index = index; + cd->flow_type = type; fwspec_parent = &domain_data->parent_irqs[index]; irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,