From patchwork Thu May 23 08:38:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 2605671 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id 2D459DFB78 for ; Thu, 23 May 2013 08:46:16 +0000 (UTC) Received: from merlin.infradead.org ([205.233.59.134]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UfR9m-00080B-JM; Thu, 23 May 2013 08:45:55 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UfR4e-0004sG-QH; Thu, 23 May 2013 08:40:36 +0000 Received: from mail-la0-x22e.google.com ([2a00:1450:4010:c03::22e]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UfR3v-0004n5-Ar for linux-arm-kernel@lists.infradead.org; Thu, 23 May 2013 08:39:54 +0000 Received: by mail-la0-f46.google.com with SMTP id er20so2959862lab.33 for ; Thu, 23 May 2013 01:39:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=vbZcVirqJWSyj+x17mvhRV9+40/duxRRKhT6jOkf9sY=; b=IEyhoNfVBwJC/kcPkOs7JGBGCnHYRzWNGRC1SJ8bbJ1yqQEBebS9+9ZfuZT+XWkgsq D0Hbudrmn6EyE1cZA7jZOK/3TWxckzyi8Yxd4Yl7qKGiO3dec4oHnamVbkRqjSTBVMGr 21vWSrKfLUr4f49Z1UCrcI/WDxyDEisad74mbN8xUDY0Nihqqzwxru3kiWXSkGQLFQxI kwI8wD4z5YVPv5hnLrfzHUOqdn40d4p1/w10AcjZMMG7y2j3t8cNPcwssDo+JUp6ElvJ J4uSOWrKD/xexsz8Z1mBjDW98qsGvBrP+NuAOJwfS3m0bwU2egpiGSPlzLvs7fInwCr3 Zslw== X-Received: by 10.152.21.225 with SMTP id y1mr5903315lae.28.1369298368850; Thu, 23 May 2013 01:39:28 -0700 (PDT) Received: from omicron.terra (s83-180-236-44.cust.tele2.se. [83.180.236.44]) by mx.google.com with ESMTPSA id e3sm4306975lbf.17.2013.05.23.01.39.25 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 23 May 2013 01:39:26 -0700 (PDT) Received: from johan by omicron.terra with local (Exim 4.80.1) (envelope-from ) id 1UfR3R-0006Q3-4C; Thu, 23 May 2013 10:39:21 +0200 From: Johan Hovold To: Nicolas Ferre Subject: [PATCH v3 4/5] rtc-at91rm9200: add shadow interrupt mask Date: Thu, 23 May 2013 10:38:54 +0200 Message-Id: <1369298335-24597-5-git-send-email-jhovold@gmail.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1369298335-24597-1-git-send-email-jhovold@gmail.com> References: <1364983415-20298-1-git-send-email-jhovold@gmail.com> <1369298335-24597-1-git-send-email-jhovold@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130523_043951_538189_3294FD6A X-CRM114-Status: GOOD ( 18.73 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (jhovold[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Johan Hovold , Douglas Gilbert , linux-kernel@vger.kernel.org, Ludovic Desroches , Robert Nelson , Jean-Christophe PLAGNIOL-VILLARD , linux-arm-kernel@lists.infradead.org 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: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add shadow interrupt-mask register which can be used on SoCs where the actual hardware register is broken. Note that some care needs to be taken to make sure the shadow mask corresponds to the actual hardware state. The added overhead is not an issue for the non-broken SoCs due to the relatively infrequent interrupt-mask updates. We do, however, only use the shadow mask value as a fall-back when it actually needed as there is still a theoretical possibility that the mask is incorrect (see the code for details). Signed-off-by: Johan Hovold --- drivers/rtc/rtc-at91rm9200.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 9592d08..205701e 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -43,6 +44,7 @@ #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ struct at91_rtc_config { + bool use_shadow_imr; }; static const struct at91_rtc_config *at91_rtc_config; @@ -50,20 +52,55 @@ static DECLARE_COMPLETION(at91_rtc_updated); static unsigned int at91_alarm_year = AT91_RTC_EPOCH; static void __iomem *at91_rtc_regs; static int irq; +static DEFINE_SPINLOCK(at91_rtc_lock); +static u32 at91_rtc_shadow_imr; static void at91_rtc_write_ier(u32 mask) { + unsigned long flags; + + spin_lock_irqsave(&at91_rtc_lock, flags); + at91_rtc_shadow_imr |= mask; at91_rtc_write(AT91_RTC_IER, mask); + spin_unlock_irqrestore(&at91_rtc_lock, flags); } static void at91_rtc_write_idr(u32 mask) { + unsigned long flags; + + spin_lock_irqsave(&at91_rtc_lock, flags); at91_rtc_write(AT91_RTC_IDR, mask); + /* + * Register read back (of any RTC-register) needed to make sure + * IDR-register write has reached the peripheral before updating + * shadow mask. + * + * Note that there is still a possibility that the mask is updated + * before interrupts have actually been disabled in hardware. The only + * way to be certain would be to poll the IMR-register, which is is + * the very register we are trying to emulate. The register read back + * is a reasonable heuristic. + */ + at91_rtc_read(AT91_RTC_SR); + at91_rtc_shadow_imr &= ~mask; + spin_unlock_irqrestore(&at91_rtc_lock, flags); } static u32 at91_rtc_read_imr(void) { - return at91_rtc_read(AT91_RTC_IMR); + unsigned long flags; + u32 mask; + + if (at91_rtc_config->use_shadow_imr) { + spin_lock_irqsave(&at91_rtc_lock, flags); + mask = at91_rtc_shadow_imr; + spin_unlock_irqrestore(&at91_rtc_lock, flags); + } else { + mask = at91_rtc_read(AT91_RTC_IMR); + } + + return mask; } /*