From patchwork Fri Nov 29 13:32:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentine Barshak X-Patchwork-Id: 3258291 Return-Path: X-Original-To: patchwork-linux-sh@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 2D6B79F371 for ; Fri, 29 Nov 2013 13:32:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6FE6C20681 for ; Fri, 29 Nov 2013 13:32:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3D2E62067D for ; Fri, 29 Nov 2013 13:32:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753740Ab3K2Nc0 (ORCPT ); Fri, 29 Nov 2013 08:32:26 -0500 Received: from mail-lb0-f178.google.com ([209.85.217.178]:59589 "EHLO mail-lb0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752819Ab3K2NcZ (ORCPT ); Fri, 29 Nov 2013 08:32:25 -0500 Received: by mail-lb0-f178.google.com with SMTP id c11so7008190lbj.37 for ; Fri, 29 Nov 2013 05:32:24 -0800 (PST) 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; bh=L9ubdP4gf+D5NNJumHFLXJG+cEAm7Af+RQCVUeKNXQQ=; b=jIFsQAUgLwSVsOvelD6IcKmQfvoDthGTNIoaKJSJLTxUwM1ujJKkjVGbqb+JyWfUUS WoiTyDk8diYdJE76StOfHwjPfr0nT03UlnRuLxR4Xq2R808HqZW+OxDOfvbGT1Jrqar4 sbKV2yImUMGltcvBmr1FeUh1Dal2TxOu/FVRtBVHvj5XZzt68LrDB4Lj7iYe7elURdYB haQZD+Rhb+LgUvj0uBTkLq0I64P1kKBOZtcM6U8tULu2UuZtRkoXBAaOfXdQNhwC+bxy 2J0ZMYW3pqe1TMSOkP7eWU0L9mpY7WcR5frz65G6m6p1+Dz8zxe0xFerIXLjdOexMB1W Jw9g== X-Gm-Message-State: ALoCoQm/WDdi68IvakoNZ/x0G3zo3pwRWVhwwUZ1cGNFsHeW+MXUeKpIFoYWZngQptQNwgj4TNR2 X-Received: by 10.152.22.131 with SMTP id d3mr642394laf.52.1385731942989; Fri, 29 Nov 2013 05:32:22 -0800 (PST) Received: from black.localnet ([93.100.122.208]) by mx.google.com with ESMTPSA id n13sm7970518lbl.17.2013.11.29.05.32.21 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 29 Nov 2013 05:32:22 -0800 (PST) From: Valentine Barshak To: linux-sh@vger.kernel.org, linux-gpio@vger.kernel.org Cc: Simon Horman , Magnus Damm , Laurent Pinchart , Linus Walleij Subject: [PATCH] gpio: rcar: Fix level interrupt handling Date: Fri, 29 Nov 2013 17:32:20 +0400 Message-Id: <1385731940-25359-1-git-send-email-valentine.barshak@cogentembedded.com> X-Mailer: git-send-email 1.8.3.1 Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham 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 According to the manual, if a port is set for level detection using the corresponding bit in the edge/level select register and an external level interrupt signal is asserted, the corresponding bit in INTDT does not use the FF to hold the input. Thus, writing 1 to the corresponding bits in INTCLR cannot clear the corresponding bits in the INTDT register. Instead, when an external input signal is stopped, the corresponding bit in INTDT is cleared automatically. Since the INTDT bit cannot be cleared for the level interrupts until the interrupt signal is stopped, we end up with the infinite loop when using deferred (threaded) IRQ handling. Workaround the issue by dropping level interrupts from the pending mask once the interrupt is handled. If the IRQ is not cleared by the handler, it will be invoked again when the interrupt is re-enabled. Signed-off-by: Valentine Barshak --- drivers/gpio/gpio-rcar.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d3f15ae..918a1de 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -166,12 +166,18 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type) static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) { struct gpio_rcar_priv *p = dev_id; - u32 pending; + u32 pending, mask = 0; unsigned int offset, irqs_handled = 0; - while ((pending = gpio_rcar_read(p, INTDT))) { + /* + * Level interrupts cannot be cleared in the INTDT, + * so we just drop them from the pending mask when + * the interrupt is handled. + */ + while ((pending = gpio_rcar_read(p, INTDT) & ~mask)) { offset = __ffs(pending); gpio_rcar_write(p, INTCLR, BIT(offset)); + mask |= BIT(offset) & ~gpio_rcar_read(p, EDGLEVEL); generic_handle_irq(irq_find_mapping(p->irq_domain, offset)); irqs_handled++; }