From patchwork Mon Jul 27 21:28:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Klimov X-Patchwork-Id: 6876771 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 00414C05AC for ; Mon, 27 Jul 2015 21:28:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0A217206EB for ; Mon, 27 Jul 2015 21:28:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7D96E2071E for ; Mon, 27 Jul 2015 21:28:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754742AbbG0V2h (ORCPT ); Mon, 27 Jul 2015 17:28:37 -0400 Received: from mail-lb0-f175.google.com ([209.85.217.175]:34581 "EHLO mail-lb0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753831AbbG0V2g (ORCPT ); Mon, 27 Jul 2015 17:28:36 -0400 Received: by lbbzr7 with SMTP id zr7so62203479lbb.1 for ; Mon, 27 Jul 2015 14:28:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:subject:from:to:cc:date:content-type:mime-version :content-transfer-encoding; bh=e/gJEfM+JW3JLlLgWvxBkqesh13HRpfU8EYaDyWm2i0=; b=1KA8mkVDRddnLralVBxaQKQMr9HISWucZmwhN/dtcItv7TOU77rM9KgNAN9K4fex+a wfKsiaew1j+wTUOu1Ic6cGIQhRaZD7clA2zRIRL6xK8FHV48K84zQjmPdnXFoj4Kwzfg OzHoo2ydTyAyUdXlPUYbcxhZarWQSqN8Zex73KvQD49SViQ5HRJ754rTx58Kp+lMa4s1 U+aeGv46EvHaYVAgE3O71SufK5301SJRQvjOwJq6u3zQvoQ5zsWGMnJRo+HTDVe3Xutf C5lbZN8Rd5CtngUn7sAg84CDxjJB3bWbuaCV1FDjBw9i6ZtPiIOTc6wJpFaoN0dXO3gE T81g== X-Received: by 10.112.141.8 with SMTP id rk8mr28542975lbb.87.1438032514131; Mon, 27 Jul 2015 14:28:34 -0700 (PDT) Received: from [192.168.0.101] (ip-46-73-144-13.bb.netbynet.ru. [46.73.144.13]) by smtp.gmail.com with ESMTPSA id r6sm4197479lbw.10.2015.07.27.14.28.32 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 27 Jul 2015 14:28:33 -0700 (PDT) Message-ID: <1438032512.17734.47.camel@gmail.com> Subject: [RFC PATCH 1/3] clocksource: exynos_mct: allow mct to read counter from coprocessor From: Alexey Klimov To: linux-samsung-soc@vger.kernel.org, daniel.lezcano@linaro.org, dianders@chromium.org, chirantan@chromium.org Cc: klimov.linux@gmail.com, t.dakhran@gmail.com, k.kozlowski@samsung.com, kgene@kernel.org, tglx@linutronix.de, linux-arm-kernel@lists.infradead.org, yury.norov@gmail.com Date: Tue, 28 Jul 2015 00:28:32 +0300 X-Mailer: Evolution 3.16.3-1 Mime-Version: 1.0 Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-8.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 It was discovered that 64-bit mmio MCT counter holds the same value as ARM arch timer 64-bit physical counter. Even more: arch timer and MCT are same underlying hardware timer. Patch adds code to MCT to allow it to read 64-bit counter from coprocessor cp15 registers since it's way more faster than reading the same counter from MCT mmio region. That functionality triggers only if special property use-cp15-phys-counter is present in device tree, only on 32-bit ARMv7 systems and only if HYP mode is available. Idea of rewriting accessors is taken from arm_arch_timer.c. By default MCT will read counter from mmio since it's guaranteed to work. Signed-off-by: Alexey Klimov --- drivers/clocksource/exynos_mct.c | 77 ++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 10 deletions(-) diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 9064ff7..039b41c 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -26,6 +26,9 @@ #include #include +#include /* for cp15 physical arch timer counter */ +#include /* for checking HYP mode */ + #define EXYNOS4_MCTREG(x) (x) #define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100) #define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104) @@ -82,6 +85,17 @@ static unsigned long clk_rate; static unsigned int mct_int_type; static int mct_irqs[MCT_NR_IRQS]; +static u32 notrace __exynos4_read_count_32(void); +static u64 __exynos4_read_count_64(void); + +/* + * Default to __exynos4_read_count_{32,64} functions that reads counter from + * MCT mmio region and this method is guaranteed + * to exist (if MCT was successfully initialized). + */ +u32 (*exynos4_read_count_32)(void) = __exynos4_read_count_32; +u64 (*exynos4_read_count_64)(void) = __exynos4_read_count_64; + struct mct_clock_event_device { struct clock_event_device evt; unsigned long base; @@ -163,16 +177,16 @@ static void exynos4_mct_frc_start(void) } /** - * exynos4_read_count_64 - Read all 64-bits of the global counter + * __exynos4_read_count_64 - Read all 64-bits of the global counter * - * This will read all 64-bits of the global counter taking care to make sure - * that the upper and lower half match. Note that reading the MCT can be quite - * slow (hundreds of nanoseconds) so you should use the 32-bit (lower half - * only) version when possible. + * This will read all 64-bits of the global counter from MCT mmio region + * taking care to make sure that the upper and lower half match. + * Note that reading the MCT can be quite slow (hundreds of nanoseconds) + * so you should use the 32-bit (lower half only) version when possible. * * Returns the number of cycles in the global counter. */ -static u64 exynos4_read_count_64(void) +static u64 __exynos4_read_count_64(void) { unsigned int lo, hi; u32 hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U); @@ -187,18 +201,45 @@ static u64 exynos4_read_count_64(void) } /** - * exynos4_read_count_32 - Read the lower 32-bits of the global counter + * __exynos4_read_cp15_count_64 - Read all 64-bits of the global counter + * from coprocessor regisers. * - * This will read just the lower 32-bits of the global counter. This is marked - * as notrace so it can be used by the scheduler clock. + * Note that reading here is faster than reading from MCT mmio region. + * + * Returns the number of cycles in the global counter. + */ +static u64 __exynos4_read_cp15_count_64(void) +{ + return arch_counter_get_cntpct(); +} + +/** + * __exynos4_read_count_32 - Read the lower 32-bits of the global counter + * + * This will read just the lower 32-bits of the global counter from + * MCT mmio region. + * This is marked as notrace so it can be used by the scheduler clock. * * Returns the number of cycles in the global counter (lower 32 bits). */ -static u32 notrace exynos4_read_count_32(void) +static u32 notrace __exynos4_read_count_32(void) { return readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L); } +/** + * __exynos4_read_cp15_count_32 - Read the lower 32-bits of the global counter + * + * This will read global counter from coprocessor regisers. + * This is marked as notrace so it can be used by the scheduler clock. + * + * Returns the number of cycles in the global counter (lower 32 bits). + */ +static u32 notrace __exynos4_read_cp15_count_32(void) +{ + return arch_counter_get_cntpct(); +} + static cycle_t exynos4_frc_read(struct clocksource *cs) { return exynos4_read_count_32(); @@ -599,6 +640,22 @@ static void __init mct_init_dt(struct device_node *np, unsigned int int_type) for (i = MCT_L0_IRQ; i < nr_irqs; i++) mct_irqs[i] = irq_of_parse_and_map(np, i); + /* + * If use-cp15-phys-counter property is present in device tree + * then use CP15 ARM arch timer 64-bit physical counter + * to speedup reading since it keeps the same value like + * 64-bit counter in MCT mmio region. + * If HYP mode is available we can rely on physical + * timer counter to be accessible from PL1. + */ + if (IS_ENABLED(CONFIG_ARM) && is_hyp_mode_available() && + of_property_read_bool(np, "use-cp15-phys-counter")) { + + /* point MCT functions to read counter from coprocessor */ + exynos4_read_count_32 = __exynos4_read_cp15_count_32; + exynos4_read_count_64 = __exynos4_read_cp15_count_64; + } + exynos4_timer_resources(np, of_iomap(np, 0)); exynos4_clocksource_init(); exynos4_clockevent_init();