From owner-svn-src-head@FreeBSD.ORG Fri Dec 28 01:38:44 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 2A52B69E; Fri, 28 Dec 2012 01:38:44 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 0DE578FC08; Fri, 28 Dec 2012 01:38:44 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBS1chl4022182; Fri, 28 Dec 2012 01:38:43 GMT (envelope-from gonzo@svn.freebsd.org) Received: (from gonzo@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBS1chFm022181; Fri, 28 Dec 2012 01:38:43 GMT (envelope-from gonzo@svn.freebsd.org) Message-Id: <201212280138.qBS1chFm022181@svn.freebsd.org> From: Oleksandr Tymoshenko Date: Fri, 28 Dec 2012 01:38:43 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r244758 - head/sys/arm/broadcom/bcm2835 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Dec 2012 01:38:44 -0000 Author: gonzo Date: Fri Dec 28 01:38:43 2012 New Revision: 244758 URL: http://svnweb.freebsd.org/changeset/base/244758 Log: Fix event timer on Raspberry Pi - Disable interrupt when updating compare value in order to make this operation atomical - Increase minimum period for event timer. Systimer on BCM2835 is compare timer, so if minimum period is too small it might be less then fraction of time between "read current value" and "set compare timer" operations. It means that when timer is armed actual counter value is more then compare value and it will take whole cycle (~32sec for 1MHz timer) to fire interrupt. Submitted by: Daisuke Aoyama Modified: head/sys/arm/broadcom/bcm2835/bcm2835_systimer.c Modified: head/sys/arm/broadcom/bcm2835/bcm2835_systimer.c ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_systimer.c Fri Dec 28 01:23:12 2012 (r244757) +++ head/sys/arm/broadcom/bcm2835/bcm2835_systimer.c Fri Dec 28 01:38:43 2012 (r244758) @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #define DEFAULT_TIMER 3 #define DEFAULT_FREQUENCY 1000000 +#define MIN_PERIOD 100LLU #define SYSTIMER_CS 0x00 #define SYSTIMER_CLO 0x04 @@ -123,17 +124,24 @@ bcm_systimer_start(struct eventtimer *et struct systimer *st = et->et_priv; uint32_t clo; uint32_t count; + register_t s; if (first != NULL) { - st->enabled = 1; count = (st->et.et_frequency * (first->frac >> 32)) >> 32; if (first->sec != 0) count += st->et.et_frequency * first->sec; + s = intr_disable(); clo = bcm_systimer_tc_read_4(SYSTIMER_CLO); clo += count; + /* + * Clear pending interrupts + */ + bcm_systimer_tc_write_4(SYSTIMER_CS, (1 << st->index)); bcm_systimer_tc_write_4(SYSTIMER_C0 + st->index*4, clo); + st->enabled = 1; + intr_restore(s); return (0); } @@ -154,7 +162,13 @@ static int bcm_systimer_intr(void *arg) { struct systimer *st = (struct systimer *)arg; + uint32_t cs; + + cs = bcm_systimer_tc_read_4(SYSTIMER_CS); + if ((cs & (1 << st->index)) == 0) + return (FILTER_STRAY); + /* ACK interrupt */ bcm_systimer_tc_write_4(SYSTIMER_CS, (1 << st->index)); if (st->enabled) { if (st->et.et_active) { @@ -226,7 +240,7 @@ bcm_systimer_attach(device_t dev) sc->st[DEFAULT_TIMER].et.et_frequency = sc->sysclk_freq; sc->st[DEFAULT_TIMER].et.et_min_period.sec = 0; sc->st[DEFAULT_TIMER].et.et_min_period.frac = - ((0x00000002LLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32; + ((MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32; sc->st[DEFAULT_TIMER].et.et_max_period.sec = 0xfffffff0U / sc->st[DEFAULT_TIMER].et.et_frequency; sc->st[DEFAULT_TIMER].et.et_max_period.frac = ((0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32;