From owner-svn-src-all@freebsd.org Thu Jun 14 17:18:16 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4B71A101593A; Thu, 14 Jun 2018 17:18:16 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 00C5E75BC6; Thu, 14 Jun 2018 17:18:16 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id BBD653938; Thu, 14 Jun 2018 17:18:15 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w5EHIFa5093608; Thu, 14 Jun 2018 17:18:15 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w5EHIFnE093607; Thu, 14 Jun 2018 17:18:15 GMT (envelope-from manu@FreeBSD.org) Message-Id: <201806141718.w5EHIFnE093607@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Thu, 14 Jun 2018 17:18:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r335156 - head/sys/arm/arm X-SVN-Group: head X-SVN-Commit-Author: manu X-SVN-Commit-Paths: head/sys/arm/arm X-SVN-Commit-Revision: 335156 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Jun 2018 17:18:16 -0000 Author: manu Date: Thu Jun 14 17:18:15 2018 New Revision: 335156 URL: https://svnweb.freebsd.org/changeset/base/335156 Log: arm timer: Add workaround for Allwinner A64 timer The timer present in allwinner A64 SoC is unstable, value can jump backward or forward. It was found that when bit 11 and upper roll over the low bits can sometimes being read as all as 1 or all as 0. Simply ignore the values for those cases. Modified: head/sys/arm/arm/generic_timer.c Modified: head/sys/arm/arm/generic_timer.c ============================================================================== --- head/sys/arm/arm/generic_timer.c Thu Jun 14 17:09:33 2018 (r335155) +++ head/sys/arm/arm/generic_timer.c Thu Jun 14 17:18:15 2018 (r335156) @@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$"); struct arm_tmr_softc { struct resource *res[4]; void *ihl[4]; + uint64_t (*get_cntxct)(bool); uint32_t clkfreq; struct eventtimer et; bool physical; @@ -142,6 +143,28 @@ get_freq(void) } static uint64_t +get_cntxct_a64_unstable(bool physical) +{ + uint64_t val +; + isb(); + if (physical) { + do { + val = get_el0(cntpct); + } + while (((val + 1) & 0x7FF) <= 1); + } + else { + do { + val = get_el0(cntvct); + } + while (((val + 1) & 0x7FF) <= 1); + } + + return (val); +} + +static uint64_t get_cntxct(bool physical) { uint64_t val; @@ -226,7 +249,7 @@ static unsigned arm_tmr_get_timecount(struct timecounter *tc) { - return (get_cntxct(arm_tmr_sc->physical)); + return (arm_tmr_sc->get_cntxct(arm_tmr_sc->physical)); } static int @@ -379,6 +402,7 @@ arm_tmr_attach(device_t dev) if (arm_tmr_sc) return (ENXIO); + sc->get_cntxct = &get_cntxct_a64_unstable; #ifdef FDT /* Get the base clock frequency */ node = ofw_bus_get_node(dev); @@ -387,6 +411,13 @@ arm_tmr_attach(device_t dev) sizeof(clock)); if (error > 0) sc->clkfreq = clock; + + if (OF_hasprop(node, "allwinner,sun50i-a64-unstable-timer")) { + sc->get_cntxct = &get_cntxct_a64_unstable; + if (bootverbose) + device_printf(dev, + "Enabling allwinner unstable timer workaround\n"); + } } #endif @@ -518,10 +549,10 @@ arm_tmr_do_delay(int usec, void *arg) else counts = usec * counts_per_usec; - first = get_cntxct(sc->physical); + first = sc->get_cntxct(sc->physical); while (counts > 0) { - last = get_cntxct(sc->physical); + last = sc->get_cntxct(sc->physical); counts -= (int32_t)(last - first); first = last; }