From patchwork Fri Jan 20 15:56:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 9528867 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 38BA3601B7 for ; Fri, 20 Jan 2017 15:57:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2E9E1286AB for ; Fri, 20 Jan 2017 15:57:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 21EA8286AE; Fri, 20 Jan 2017 15:57:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00 autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A8CF2286AB for ; Fri, 20 Jan 2017 15:57:09 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cUbYo-0005ss-K8; Fri, 20 Jan 2017 15:57:06 +0000 Received: from mail.free-electrons.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cUbYj-0005j1-SR for linux-arm-kernel@lists.infradead.org; Fri, 20 Jan 2017 15:57:03 +0000 Received: by mail.free-electrons.com (Postfix, from userid 110) id 0B51D20C07; Fri, 20 Jan 2017 16:56:50 +0100 (CET) Received: from localhost (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id DB3EC20B7D; Fri, 20 Jan 2017 16:56:49 +0100 (CET) From: Maxime Ripard To: Alexandre Belloni , Alessandro Zummo , Chen-Yu Tsai Subject: [PATCH 2/6] rtc: sun6i: Add some locking Date: Fri, 20 Jan 2017 16:56:39 +0100 Message-Id: <9b5c8ed82f636fd2061a9b7933c0e6b65d868643.1484927680.git-series.maxime.ripard@free-electrons.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170120_075702_220344_A4C5A512 X-CRM114-Status: GOOD ( 13.93 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, Maxime Ripard , Rob Herring , rtc-linux@googlegroups.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Some registers have a read-modify-write access pattern that are not atomic. Add some locking to prevent from concurrent accesses. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai --- drivers/rtc/rtc-sun6i.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 408dd512a6ac..872d18609183 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -125,6 +125,8 @@ struct sun6i_rtc_dev { struct clk_hw hw; struct clk_hw *int_osc; struct clk *losc; + + spinlock_t lock; }; static struct sun6i_rtc_dev *sun6i_rtc; @@ -155,16 +157,19 @@ static u8 sun6i_rtc_osc_get_parent(struct clk_hw *hw) static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index) { struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw); + unsigned long flags; u32 val; if (index > 1) return -EINVAL; + spin_lock_irqsave(&rtc->lock, flags); val = readl(rtc->base + SUN6I_LOSC_CTRL); val &= ~SUN6I_LOSC_CTRL_EXT_OSC; val |= SUN6I_LOSC_CTRL_KEY; val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0; writel(val, rtc->base + SUN6I_LOSC_CTRL); + spin_unlock_irqrestore(&rtc->lock, flags); return 0; } @@ -187,6 +192,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); if (!rtc) pr_crit("Can't allocate RTC structure\n"); + spin_lock_init(&rtc->lock); rtc->base = of_io_request_and_map(node, 0, of_node_full_name(node)); if (!rtc->base) { @@ -246,8 +252,10 @@ CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc", static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) { struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; + irqreturn_t ret = IRQ_NONE; u32 val; + spin_lock(&chip->lock); val = readl(chip->base + SUN6I_ALRM_IRQ_STA); if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { @@ -256,10 +264,11 @@ static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); - return IRQ_HANDLED; + ret = IRQ_HANDLED; } + spin_unlock(&chip->lock); - return IRQ_NONE; + return ret; } static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) @@ -267,6 +276,7 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) u32 alrm_val = 0; u32 alrm_irq_val = 0; u32 alrm_wake_val = 0; + unsigned long flags; if (to) { alrm_val = SUN6I_ALRM_EN_CNT_EN; @@ -277,9 +287,11 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) chip->base + SUN6I_ALRM_IRQ_STA); } + spin_lock_irqsave(&chip->lock, flags); writel(alrm_val, chip->base + SUN6I_ALRM_EN); writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); + spin_unlock_irqrestore(&chip->lock, flags); } static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) @@ -318,11 +330,15 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) { struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + unsigned long flags; u32 alrm_st; u32 alrm_en; + spin_lock_irqsave(&chip->lock, flags); alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); + spin_unlock_irqrestore(&chip->lock, flags); + wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); rtc_time_to_tm(chip->alarm, &wkalrm->time);