From patchwork Mon Apr 11 02:22:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Crystal Wood X-Patchwork-Id: 8796031 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 800ED9F39A for ; Mon, 11 Apr 2016 02:33:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 82CA620268 for ; Mon, 11 Apr 2016 02:33:27 +0000 (UTC) Received: from bombadil.infradead.org (unknown [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7DD5620260 for ; Mon, 11 Apr 2016 02:33:26 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1apRVn-0002MR-0D; Mon, 11 Apr 2016 02:23:35 +0000 Received: from host.buserror.net ([209.198.135.123]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1apRVb-0002GC-O3 for linux-arm-kernel@lists.infradead.org; Mon, 11 Apr 2016 02:23:24 +0000 Received: from c-75-72-173-242.hsd1.mn.comcast.net ([75.72.173.242] helo=snotra.am.freescale.net) by host.buserror.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1apRUw-0000tw-2v; Sun, 10 Apr 2016 21:22:43 -0500 From: Scott Wood To: Shawn Guo , Russell King , Catalin Marinas , Will Deacon Date: Sun, 10 Apr 2016 21:22:33 -0500 Message-Id: <1460341353-15619-3-git-send-email-oss@buserror.net> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1460341353-15619-1-git-send-email-oss@buserror.net> References: <1460341353-15619-1-git-send-email-oss@buserror.net> X-SA-Exim-Connect-IP: 75.72.173.242 X-SA-Exim-Mail-From: oss@buserror.net X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RDNS_NONE,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Subject: [RFC PATCH 2/2] ARM64: arch_timer: Work around QorIQ Erratum A-009971 X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:57:07 +0000) X-SA-Exim-Scanned: Yes (on host.buserror.net) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160410_192323_919927_00DEFE8B X-CRM114-Status: GOOD ( 12.91 ) X-Spam-Score: -5.2 (-----) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Scott Wood , Priyanka Jain , mbrugger@suse.com, stuart.yoder@nxp.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 From: Priyanka Jain Erratum A-009971 says that it is possible for the timer value register to be written incorrectly, resulting in "an incorrect and potentially very long timeout". The workaround is to read the timer count immediately before and after writing the timer value register, and repeat if the counter reads don't match. This erratum can be found on LS2080A. Signed-off-by: Priyanka Jain [scottwood: cleanup and fixes] Signed-off-by: Scott Wood --- .../devicetree/bindings/arm/arch_timer.txt | 5 ++++ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 1 + arch/arm64/include/asm/arch_timer.h | 27 ++++++++++++++++++++-- drivers/clocksource/arm_arch_timer.c | 3 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt index 7117fbd..ab4d3b1 100644 --- a/Documentation/devicetree/bindings/arm/arch_timer.txt +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt @@ -29,6 +29,11 @@ to deliver its interrupts via SPIs. QorIQ erratum A-008585, which says reading the timer is unreliable unless the same value is returned by back-to-back reads. +- fsl,erratum-a009971 : A boolean property. Indicates the presence of + QorIQ erratum A-009971, which says writing the timer value register + is unreliable unless timer count reads before and after the timer write + return the same value. + ** Optional properties: - arm,cpu-registers-not-fw-configured : Firmware does not initialize diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi index 0270ccf..529e441 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi @@ -172,6 +172,7 @@ <1 11 0x8>, /* Virtual PPI, active-low */ <1 10 0x8>; /* Hypervisor PPI, active-low */ fsl,erratum-a008585; + fsl,erratum-a009971; }; pmu { diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 9367ee3..1867e60 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -28,6 +28,7 @@ #include extern bool arm_arch_timer_reread; +extern bool arm_arch_timer_rewrite; /* QorIQ errata workarounds */ #define ARCH_TIMER_REREAD(reg) ({ \ @@ -52,6 +53,20 @@ extern bool arm_arch_timer_reread; _val; \ }) +#define ARCH_TIMER_TVAL_REWRITE(pv, val) do { \ + u64 _cnt_old, _cnt_new; \ + int _timeout = 200; \ + do { \ + asm volatile("mrs %0, cntvct_el0;" \ + "msr cnt" pv "_tval_el0, %2;" \ + "mrs %1, cntvct_el0" \ + : "=&r" (_cnt_old), "=r" (_cnt_new) \ + : "r" (val)); \ + _timeout--; \ + } while (_cnt_old != _cnt_new && _timeout); \ + WARN_ON_ONCE(!_timeout); \ +} while (0) + /* * These register accessors are marked inline so the compiler can * nicely work out which register we want, and chuck away the rest of @@ -66,7 +81,11 @@ void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) asm volatile("msr cntp_ctl_el0, %0" : : "r" (val)); break; case ARCH_TIMER_REG_TVAL: - asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); + if (arm_arch_timer_rewrite) + ARCH_TIMER_TVAL_REWRITE("p", val); + else + asm volatile("msr cntp_tval_el0, %0" : : + "r" (val)); break; } } else if (access == ARCH_TIMER_VIRT_ACCESS) { @@ -75,7 +94,11 @@ void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) asm volatile("msr cntv_ctl_el0, %0" : : "r" (val)); break; case ARCH_TIMER_REG_TVAL: - asm volatile("msr cntv_tval_el0, %0" : : "r" (val)); + if (arm_arch_timer_rewrite) + ARCH_TIMER_TVAL_REWRITE("v", val); + else + asm volatile("msr cntv_tval_el0, %0" : : + "r" (val)); break; } } diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5ed7c7f..82b32cb 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -81,6 +81,7 @@ static bool arch_timer_mem_use_virtual; bool arm_arch_timer_reread; /* QorIQ erratum A-008585 */ EXPORT_SYMBOL(arm_arch_timer_reread); +bool arm_arch_timer_rewrite; /* QorIQ erratum A-009971 */ /* * Architected system timer support. @@ -767,6 +768,8 @@ static void __init arch_timer_of_init(struct device_node *np) arch_timer_c3stop = !of_property_read_bool(np, "always-on"); arm_arch_timer_reread = of_property_read_bool(np, "fsl,erratum-a008585"); + arm_arch_timer_rewrite = + of_property_read_bool(np, "fsl,erratum-a009971"); /* * If we cannot rely on firmware initializing the timer registers then