hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/arch/m68k/atari/time.c
....@@ -16,6 +16,7 @@
1616 #include <linux/init.h>
1717 #include <linux/rtc.h>
1818 #include <linux/bcd.h>
19
+#include <linux/clocksource.h>
1920 #include <linux/delay.h>
2021 #include <linux/export.h>
2122
....@@ -24,12 +25,29 @@
2425 DEFINE_SPINLOCK(rtc_lock);
2526 EXPORT_SYMBOL_GPL(rtc_lock);
2627
28
+static u64 atari_read_clk(struct clocksource *cs);
29
+
30
+static struct clocksource atari_clk = {
31
+ .name = "mfp",
32
+ .rating = 100,
33
+ .read = atari_read_clk,
34
+ .mask = CLOCKSOURCE_MASK(32),
35
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
36
+};
37
+
38
+static u32 clk_total;
39
+static u8 last_timer_count;
40
+
2741 static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
2842 {
2943 irq_handler_t timer_routine = dev_id;
3044 unsigned long flags;
3145
3246 local_irq_save(flags);
47
+ do {
48
+ last_timer_count = st_mfp.tim_dt_c;
49
+ } while (last_timer_count == 1);
50
+ clk_total += INT_TICKS;
3351 timer_routine(0, NULL);
3452 local_irq_restore(flags);
3553
....@@ -44,32 +62,33 @@
4462 /* start timer C, div = 1:100 */
4563 st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
4664 /* install interrupt service routine for MFP Timer C */
47
- if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, 0, "timer",
65
+ if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, IRQF_TIMER, "timer",
4866 timer_routine))
4967 pr_err("Couldn't register timer interrupt\n");
68
+
69
+ clocksource_register_hz(&atari_clk, INT_CLK);
5070 }
5171
5272 /* ++andreas: gettimeoffset fixed to check for pending interrupt */
5373
54
-#define TICK_SIZE 10000
55
-
56
-/* This is always executed with interrupts disabled. */
57
-u32 atari_gettimeoffset(void)
74
+static u64 atari_read_clk(struct clocksource *cs)
5875 {
59
- u32 ticks, offset = 0;
76
+ unsigned long flags;
77
+ u8 count;
78
+ u32 ticks;
6079
61
- /* read MFP timer C current value */
62
- ticks = st_mfp.tim_dt_c;
63
- /* The probability of underflow is less than 2% */
64
- if (ticks > INT_TICKS - INT_TICKS / 50)
65
- /* Check for pending timer interrupt */
66
- if (st_mfp.int_pn_b & (1 << 5))
67
- offset = TICK_SIZE;
80
+ local_irq_save(flags);
81
+ /* Ensure that the count is monotonically decreasing, even though
82
+ * the result may briefly stop changing after counter wrap-around.
83
+ */
84
+ count = min(st_mfp.tim_dt_c, last_timer_count);
85
+ last_timer_count = count;
6886
69
- ticks = INT_TICKS - ticks;
70
- ticks = ticks * 10000L / INT_TICKS;
87
+ ticks = INT_TICKS - count;
88
+ ticks += clk_total;
89
+ local_irq_restore(flags);
7190
72
- return (ticks + offset) * 1000;
91
+ return ticks;
7392 }
7493
7594