From patchwork Fri Jul 5 22:53:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiko Stuebner X-Patchwork-Id: 2824430 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E62EEC0AB3 for ; Fri, 5 Jul 2013 22:54:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E087C20178 for ; Fri, 5 Jul 2013 22:54:57 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C83502017E for ; Fri, 5 Jul 2013 22:54:56 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UvEt2-0000JY-IF; Fri, 05 Jul 2013 22:53:57 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UvEsj-0000hg-Bp; Fri, 05 Jul 2013 22:53:37 +0000 Received: from gloria.sntech.de ([95.129.55.99]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UvEsh-0000h7-81 for linux-arm-kernel@lists.infradead.org; Fri, 05 Jul 2013 22:53:36 +0000 Received: from 146-52-210-25-dynip.superkabel.de ([146.52.210.25] helo=marty.localnet) by gloria.sntech.de with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1UvEsJ-0005Up-FQ; Sat, 06 Jul 2013 00:53:11 +0200 From: Heiko =?utf-8?q?St=C3=BCbner?= To: John Stultz Subject: [PATCH 3/9] clocksource: dw_apb_timer: quirk for variants with 64bit counter Date: Sat, 6 Jul 2013 00:53:09 +0200 User-Agent: KMail/1.13.7 (Linux/3.2.0-3-686-pae; KDE/4.8.4; i686; ; ) References: <201307060051.09716.heiko@sntech.de> In-Reply-To: <201307060051.09716.heiko@sntech.de> MIME-Version: 1.0 Message-Id: <201307060053.10182.heiko@sntech.de> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130705_185335_407759_B8B250BA X-CRM114-Status: GOOD ( 13.66 ) X-Spam-Score: -2.1 (--) Cc: Arnd Bergmann , devicetree-discuss@lists.ozlabs.org, linux-kernel@vger.kernel.org, Rob Herring , Olof Johansson , Dinh Nguyen , Grant Likely , Jamie Iles , Thomas Gleixner , Ulrich Prinz , 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: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This adds a quirk for IP variants containing two load_count and value registers that are used to provide 64bit accuracy on 32bit systems. The added accuracy is currently not used, the driver is only adapted to handle the different register layout and make it work on affected devices. Signed-off-by: Heiko Stuebner --- drivers/clocksource/dw_apb_timer.c | 27 +++++++++++++++++++++++++++ include/linux/dw_apb_timer.h | 6 ++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index f5e7be8..bd45351 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -56,6 +56,17 @@ static void apbt_init_regs(struct dw_apb_timer *timer, int quirks) timer->reg_control = APBTMR_N_CONTROL; timer->reg_eoi = APBTMR_N_EOI; timer->reg_int_status = APBTMR_N_INT_STATUS; + + /* + * On variants with 64bit counters some registers are + * moved further down. + */ + if (quirks & APBTMR_QUIRK_64BIT_COUNTER) { + timer->reg_current_value += 0x4; + timer->reg_control += 0x8; + timer->reg_eoi += 0x8; + timer->reg_int_status += 0x8; + } } static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs) @@ -145,6 +156,10 @@ static void apbt_set_mode(enum clock_event_mode mode, udelay(1); pr_debug("Setting clock period %lu for HZ %d\n", period, HZ); apbt_writel(timer, period, timer->reg_load_count); + + if (timer->quirks & APBTMR_QUIRK_64BIT_COUNTER) + apbt_writel(timer, 0, timer->reg_load_count + 0x4); + ctrl |= APBTMR_CONTROL_ENABLE; apbt_writel(timer, ctrl, timer->reg_control); break; @@ -168,6 +183,10 @@ static void apbt_set_mode(enum clock_event_mode mode, * running mode. */ apbt_writel(timer, ~0, timer->reg_load_count); + + if (timer->quirks & APBTMR_QUIRK_64BIT_COUNTER) + apbt_writel(timer, 0, timer->reg_load_count + 0x4); + ctrl &= ~APBTMR_CONTROL_INT; ctrl |= APBTMR_CONTROL_ENABLE; apbt_writel(timer, ctrl, timer->reg_control); @@ -199,6 +218,10 @@ static int apbt_next_event(unsigned long delta, apbt_writel(timer, ctrl, timer->reg_control); /* write new count */ apbt_writel(timer, delta, timer->reg_load_count); + + if (timer->quirks & APBTMR_QUIRK_64BIT_COUNTER) + apbt_writel(timer, 0, timer->reg_load_count + 0x4); + ctrl |= APBTMR_CONTROL_ENABLE; apbt_writel(timer, ctrl, timer->reg_control); @@ -325,6 +348,10 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) ctrl &= ~APBTMR_CONTROL_ENABLE; apbt_writel(timer, ctrl, timer->reg_control); apbt_writel(timer, ~0, timer->reg_load_count); + + if (timer->quirks & APBTMR_QUIRK_64BIT_COUNTER) + apbt_writel(timer, 0, timer->reg_load_count + 0x4); + /* enable, mask interrupt */ ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT); diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h index 7dc7166..80f6686 100644 --- a/include/linux/dw_apb_timer.h +++ b/include/linux/dw_apb_timer.h @@ -19,6 +19,12 @@ #define APBTMRS_REG_SIZE 0x14 +/* The IP uses two registers for count and values, to provide 64bit accuracy + * on 32bit platforms. The additional registers move the following registers + * down by 0x8 byte, as both the count and value registers are duplicated. + */ +#define APBTMR_QUIRK_64BIT_COUNTER BIT(0) + struct dw_apb_timer { void __iomem *base; unsigned long freq;