Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2180229imu; Sun, 18 Nov 2018 17:54:02 -0800 (PST) X-Google-Smtp-Source: AJdET5eneVua/1/DT7EiMIOvsUPmE6Al/472xAIR6KhVLKSg95S9+9IYVrJsuWJNqhcSnuaCIFxl X-Received: by 2002:a17:902:7281:: with SMTP id d1-v6mr20128721pll.284.1542592442252; Sun, 18 Nov 2018 17:54:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542592442; cv=none; d=google.com; s=arc-20160816; b=cX8NePZF54bj2TlN9amXF7wW1nZBDiQSMhZhRjwfkwLxLyXeD4Fjc4/DSrn0GjQdYm hZZDWgnYI85+61a2yYhr3lxWRtcuQW/winv0r13+wMbcD+EWyjNKJMCcw7gdoebPFklv +oJY0goQ1ph8eHKSCPK21LL2gLa+0caEfPHw6ZfV0ZbT/bZp/pRhjMdBmaK3zr1bf7oc O+FJLipwMAVVmb9Mc4v/h7EW3mmpZJDB/8PCNfn5XbOqBjRcGGhz69/xvy2I3n0HArUk PLQZXpL0MUfRZB5Amrk8tSeKqr5osy4VnDkSTdEnxhxW9OE+5rAf/IEF1+hVq/rOJpl9 yhFw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:date:subject:from:references:in-reply-to :message-id:cc:to; bh=OHzdit6Wn6iUbpbgsv0IpCVkIQOjRwmlJOW8yBRsfEU=; b=TJS7qmHF2IEW/LOJH5Xk93iduGQGGtOqxDJMSVsTYf+bpddS01mpSX9GFtQX7WWWUX ZXe+3O4iZguohtTnU2kH9qZbHE20VwpK1Pe/wVdg59jUrWlgbnrFNqVPXvn1fwILVMeb UxOBLClX526qJitfzv/dr/He+s45tx2mpdYLv9kELoA+pxUAvOAe8+6pqpTm1dlPZvvp 2Go+JOiRoPt5aEtmEOz7AC1FR6WaqtANfaG3UetF16PJWUiYeNbb+i9nZPX5YbNAWVOk mr8o9SmxDNHQzotjeepO+guH/Iq9WU7msirQH9BOhX6zW7DXHP6YmYv0htXujFibEspE zhzA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e189si20298531pfc.202.2018.11.18.17.53.46; Sun, 18 Nov 2018 17:54:02 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728330AbeKSLol (ORCPT + 99 others); Mon, 19 Nov 2018 06:44:41 -0500 Received: from kvm5.telegraphics.com.au ([98.124.60.144]:49280 "EHLO kvm5.telegraphics.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727507AbeKSLoS (ORCPT ); Mon, 19 Nov 2018 06:44:18 -0500 Received: by kvm5.telegraphics.com.au (Postfix, from userid 502) id CF73729DFC; Sun, 18 Nov 2018 20:22:17 -0500 (EST) To: Geert Uytterhoeven Cc: Andreas Schwab , Arnd Bergmann , Stephen N Chivers , Thomas Gleixner , Daniel Lezcano , Michael Schmitz , John Stultz , Linus Walleij , linux-m68k@lists.linux-m68k.org, linux-kernel@vger.kernel.org Message-Id: In-Reply-To: References: From: Finn Thain Subject: [RFC PATCH v2 07/14] m68k: atari: Convert to clocksource API Date: Mon, 19 Nov 2018 12:10:38 +1100 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a platform clocksource by adapting the existing arch_gettimeoffset implementation. Normally the MFP timer C interrupt flag would be used to check for timer counter wrap-around. Unfortunately, that flag gets cleared by the MFP itself (due to automatic EOI mode). This means that mfp_timer_c_handler() and atari_read_clk() must race when accounting for counter wrap-around. That problem is avoided here by effectively stopping the clock when it might otherwise jump backwards. This harms clock accuracy; the result is not much better than the jiffies clocksource. Also, clock error is no longer uniformly distributed. Signed-off-by: Finn Thain Acked-by: Linus Walleij --- TODO: find a spare counter for the clocksource, rather than hanging it off the HZ timer. It would be simpler to adopt the 'jiffies' clocksource here (c.f. patch for the hp300 platform in this series). Changed since v1: - Moved clk_total access to within the irq lock. - Renamed mfp_timer_handler and mfptimer_handler. - Avoid accessing the timer interrupt flag in atari_read_clk(). To get monotonicity, keep track of the previous timer counter value. --- arch/m68k/atari/time.c | 48 +++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c index fafa20f75ab9..914832e55ec5 100644 --- a/arch/m68k/atari/time.c +++ b/arch/m68k/atari/time.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -24,12 +25,27 @@ DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL_GPL(rtc_lock); +static u64 atari_read_clk(struct clocksource *cs); + +static struct clocksource atari_clk = { + .name = "mfp", + .rating = 100, + .read = atari_read_clk, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static u32 clk_total; +static u32 last_timer_count; + static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id) { irq_handler_t timer_routine = dev_id; unsigned long flags; local_irq_save(flags); + last_timer_count = st_mfp.tim_dt_c; + clk_total += INT_TICKS; timer_routine(0, NULL); local_irq_restore(flags); @@ -44,32 +60,30 @@ atari_sched_init(irq_handler_t timer_routine) /* start timer C, div = 1:100 */ st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60; /* install interrupt service routine for MFP Timer C */ - if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, 0, "timer", + if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, IRQF_TIMER, "timer", timer_routine)) pr_err("Couldn't register timer interrupt\n"); + + clocksource_register_hz(&atari_clk, INT_CLK); } /* ++andreas: gettimeoffset fixed to check for pending interrupt */ -#define TICK_SIZE 10000 - -/* This is always executed with interrupts disabled. */ -u32 atari_gettimeoffset(void) +static u64 atari_read_clk(struct clocksource *cs) { - u32 ticks, offset = 0; - - /* read MFP timer C current value */ - ticks = st_mfp.tim_dt_c; - /* The probability of underflow is less than 2% */ - if (ticks > INT_TICKS - INT_TICKS / 50) - /* Check for pending timer interrupt */ - if (st_mfp.int_pn_b & (1 << 5)) - offset = TICK_SIZE; + unsigned long flags; + u32 ticks; - ticks = INT_TICKS - ticks; - ticks = ticks * 10000L / INT_TICKS; + local_irq_save(flags); + ticks = st_mfp.tim_dt_c; + if (ticks > last_timer_count) /* timer wrapped since last interrupt */ + ticks = last_timer_count; + last_timer_count = ticks; + ticks = INT_TICKS - ticks; + ticks += clk_total; + local_irq_restore(flags); - return (ticks + offset) * 1000; + return ticks; } -- 2.18.1