hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/arm/mach-rpc/time.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/arch/arm/common/time-acorn.c
34 *
45 * Copyright (c) 1996-2000 Russell King.
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 *
107 * Changelog:
118 * 24-Sep-1996 RMK Created
....@@ -13,7 +10,7 @@
1310 * 04-Dec-1997 RMK Updated for new arch/arm/time.c
1411 * 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500
1512 */
16
-#include <linux/timex.h>
13
+#include <linux/clocksource.h>
1714 #include <linux/init.h>
1815 #include <linux/interrupt.h>
1916 #include <linux/irq.h>
....@@ -27,11 +24,15 @@
2724 #define RPC_CLOCK_FREQ 2000000
2825 #define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
2926
30
-static u32 ioc_timer_gettimeoffset(void)
27
+static u32 ioc_time;
28
+
29
+static u64 ioc_timer_read(struct clocksource *cs)
3130 {
3231 unsigned int count1, count2, status;
33
- long offset;
32
+ unsigned long flags;
33
+ u32 ticks;
3434
35
+ local_irq_save(flags);
3536 ioc_writeb (0, IOC_T0LATCH);
3637 barrier ();
3738 count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
....@@ -41,26 +42,33 @@
4142 ioc_writeb (0, IOC_T0LATCH);
4243 barrier ();
4344 count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
45
+ ticks = ioc_time + RPC_LATCH - count2;
46
+ local_irq_restore(flags);
4447
45
- offset = count2;
4648 if (count2 < count1) {
4749 /*
48
- * We have not had an interrupt between reading count1
49
- * and count2.
50
+ * The timer has not reloaded between reading count1 and
51
+ * count2, check whether an interrupt was actually pending.
5052 */
5153 if (status & (1 << 5))
52
- offset -= RPC_LATCH;
54
+ ticks += RPC_LATCH;
5355 } else if (count2 > count1) {
5456 /*
55
- * We have just had another interrupt between reading
56
- * count1 and count2.
57
+ * The timer has reloaded, so count2 indicates the new
58
+ * count since the wrap. The interrupt would not have
59
+ * been processed, so add the missed ticks.
5760 */
58
- offset -= RPC_LATCH;
61
+ ticks += RPC_LATCH;
5962 }
6063
61
- offset = (RPC_LATCH - offset) * (tick_nsec / 1000);
62
- return DIV_ROUND_CLOSEST(offset, RPC_LATCH) * 1000;
64
+ return ticks;
6365 }
66
+
67
+static struct clocksource ioctime_clocksource = {
68
+ .read = ioc_timer_read,
69
+ .mask = CLOCKSOURCE_MASK(32),
70
+ .rating = 100,
71
+};
6472
6573 void __init ioctime_init(void)
6674 {
....@@ -72,21 +80,18 @@
7280 static irqreturn_t
7381 ioc_timer_interrupt(int irq, void *dev_id)
7482 {
83
+ ioc_time += RPC_LATCH;
7584 timer_tick();
7685 return IRQ_HANDLED;
7786 }
78
-
79
-static struct irqaction ioc_timer_irq = {
80
- .name = "timer",
81
- .handler = ioc_timer_interrupt
82
-};
8387
8488 /*
8589 * Set up timer interrupt.
8690 */
8791 void __init ioc_timer_init(void)
8892 {
89
- arch_gettimeoffset = ioc_timer_gettimeoffset;
93
+ WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
9094 ioctime_init();
91
- setup_irq(IRQ_TIMER0, &ioc_timer_irq);
95
+ if (request_irq(IRQ_TIMER0, ioc_timer_interrupt, 0, "timer", NULL))
96
+ pr_err("Failed to request irq %d (timer)\n", IRQ_TIMER0);
9297 }