Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp4408188imu; Fri, 30 Nov 2018 17:01:42 -0800 (PST) X-Google-Smtp-Source: AFSGD/WdOft7yX8zN68OMUWi5zI0a1VBzTfOj4j1YYR9LXb/Ofb/gKDouk0r9qb9pbxeJYs0Rk7p X-Received: by 2002:a63:b4c:: with SMTP id a12mr6674071pgl.131.1543626102809; Fri, 30 Nov 2018 17:01:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543626102; cv=none; d=google.com; s=arc-20160816; b=I9BTE8nBMQ810oZXZZjdKxY/5uZNKrW9FLRzAGP3J6tfAcewh0Wze5Jakp3dU9hsEU 7RLbqXe6R1tice5xqaLk4cH/TJDzZI06Bx5u8COC9zaPqRO5dF9dFCukm+LauZZtiBWG lj8FbI6R/mDdRvMLs+t568OGOK5gJDPH+ydw8cB+vGZd1Qm/AJfSveLXqAGjXCK24WvG zYOYueSH9nlkpGHTg4tAFUtwWvybpbIl03LTL4gfsjGZjqxNejXOwFRD2yjmaFOEWWqg ONe7hD7x5HjDaFaiBcQD4MC2Sk2pjNJRu8GfyRYAQYxbJi9q0vyPdGIOfBEmEXESSsFb GcWg== 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=B4Ltca9TAwPDXw2MMl0MXihkMg4P7hyfisWDIY1DpUA=; b=ch9fSul1eIOIs7w2iAsukgf5NF73nhW6679RydHZZ8ZdbGNF3reDSgTIpbqWPAMNa6 OtqWWESe3l6gdCCUAlxd9h3yG1yWCltgbcb61nq4mdSM2+ghIuwqcYMRTu3bPlb3Nbaz aoeRi51osA275ilFImt0xZzxmOm4SVvem4fQ9QB8n3VDxWzoF/THpOskg+5pueSsDiuK X1n8j7O8BkfEEAj5hhhisVY5Ojrk749IYj+KZNycOSGN9gFAeGK2jLQgploJWKFF8Q68 2E7gg3sraz4z1JSjV4Qiz+B9fmjGJhTKfwxpDZ5iSJaExx0Vgo9F+EVzFQSOZNcvz2PK X4WQ== 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 q5si6498697pgr.435.2018.11.30.17.01.28; Fri, 30 Nov 2018 17:01:42 -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 S1727039AbeLAMLj (ORCPT + 99 others); Sat, 1 Dec 2018 07:11:39 -0500 Received: from kvm5.telegraphics.com.au ([98.124.60.144]:38164 "EHLO kvm5.telegraphics.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726159AbeLAMLc (ORCPT ); Sat, 1 Dec 2018 07:11:32 -0500 Received: by kvm5.telegraphics.com.au (Postfix, from userid 502) id 8630822840; Fri, 30 Nov 2018 20:00:15 -0500 (EST) To: Geert Uytterhoeven Cc: Andreas Schwab , Arnd Bergmann , Stephen N Chivers , Thomas Gleixner , Kars de Jong , Daniel Lezcano , Michael Schmitz , John Stultz , Linus Walleij , linux-m68k@lists.linux-m68k.org, linux-kernel@vger.kernel.org Message-Id: <9e87e71ff7978d7cc291c80efd98909375c0f7a0.1543625590.git.fthain@telegraphics.com.au> In-Reply-To: References: From: Finn Thain Subject: [PATCH v4 14/14] m68k: mvme16x: Handle timer counter overflow Date: Sat, 01 Dec 2018 11:53:10 +1100 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Reading the timer counter races with timer overflow (and the corresponding interrupt). This is resolved by reading the overflow register and taking this value into account. The interrupt handler must clear the overflow register when it eventually executes. Suggested-by: Thomas Gleixner Signed-off-by: Finn Thain --- TODO: find a spare counter for the clocksource, rather than hanging it off the HZ timer. --- arch/m68k/mvme16x/config.c | 45 +++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 2c109ee2a1a5..9bc2da69f80c 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -115,11 +115,11 @@ static void __init mvme16x_init_IRQ (void) m68k_setup_user_interrupt(VEC_USER, 192); } -#define pcc2chip ((volatile u_char *)0xfff42000) -#define PccSCCMICR 0x1d -#define PccSCCTICR 0x1e -#define PccSCCRICR 0x1f -#define PccTPIACKR 0x25 +#define PCC2CHIP (0xfff42000) +#define PCCSCCMICR (PCC2CHIP + 0x1d) +#define PCCSCCTICR (PCC2CHIP + 0x1e) +#define PCCSCCRICR (PCC2CHIP + 0x1f) +#define PCCTPIACKR (PCC2CHIP + 0x25) #ifdef CONFIG_EARLY_PRINTK @@ -227,10 +227,10 @@ void mvme16x_cons_write(struct console *co, const char *str, unsigned count) base_addr[CyIER] = CyTxMpty; while (1) { - if (pcc2chip[PccSCCTICR] & 0x20) + if (in_8(PCCSCCTICR) & 0x20) { /* We have a Tx int. Acknowledge it */ - sink = pcc2chip[PccTPIACKR]; + sink = in_8(PCCTPIACKR); if ((base_addr[CyLICR] >> 2) == port) { if (i == count) { /* Last char of string is now output */ @@ -359,13 +359,26 @@ static u32 clk_total; #define PCC_TIMER_CLOCK_FREQ 1000000 #define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ) +#define PCCTCMP1 (PCC2CHIP + 0x04) +#define PCCTCNT1 (PCC2CHIP + 0x08) +#define PCCTOVR1 (PCC2CHIP + 0x17) +#define PCCTIC1 (PCC2CHIP + 0x1b) + +#define PCCTOVR1_TIC_EN 0x01 +#define PCCTOVR1_COC_EN 0x02 +#define PCCTOVR1_OVR_CLR 0x04 + +#define PCCTIC1_INT_CLR 0x08 +#define PCCTIC1_INT_EN 0x10 + static irqreturn_t mvme16x_timer_int (int irq, void *dev_id) { irq_handler_t timer_routine = dev_id; unsigned long flags; local_irq_save(flags); - *(volatile unsigned char *)0xfff4201b |= 8; + out_8(PCCTIC1, in_8(PCCTIC1) | PCCTIC1_INT_CLR); + out_8(PCCTOVR1, PCCTOVR1_OVR_CLR); clk_total += PCC_TIMER_CYCLES; timer_routine(0, NULL); local_irq_restore(flags); @@ -379,10 +392,10 @@ void mvme16x_sched_init (irq_handler_t timer_routine) int irq; /* Using PCCchip2 or MC2 chip tick timer 1 */ - *(volatile unsigned long *)0xfff42008 = 0; - *(volatile unsigned long *)0xfff42004 = PCC_TIMER_CYCLES; - *(volatile unsigned char *)0xfff42017 |= 3; - *(volatile unsigned char *)0xfff4201b = 0x16; + out_be32(PCCTCNT1, 0); + out_be32(PCCTCMP1, PCC_TIMER_CYCLES); + out_8(PCCTOVR1, in_8(PCCTOVR1) | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN); + out_8(PCCTIC1, PCCTIC1_INT_EN | 6); if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER, "timer", timer_routine)) panic ("Couldn't register timer int"); @@ -401,10 +414,16 @@ void mvme16x_sched_init (irq_handler_t timer_routine) static u64 mvme16x_read_clk(struct clocksource *cs) { unsigned long flags; + u8 overflow, tmp; u32 ticks; local_irq_save(flags); - ticks = *(volatile u32 *)0xfff42008; + tmp = in_8(PCCTOVR1) >> 4; + ticks = in_be32(PCCTCNT1); + overflow = in_8(PCCTOVR1) >> 4; + if (overflow != tmp) + ticks = in_be32(PCCTCNT1); + ticks += overflow * PCC_TIMER_CYCLES; ticks += clk_total; local_irq_restore(flags); -- 2.18.1