[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211104133204.19757-4-martin.kaistra@linutronix.de>
Date: Thu, 4 Nov 2021 14:31:57 +0100
From: Martin Kaistra <martin.kaistra@...utronix.de>
To: Florian Fainelli <f.fainelli@...il.com>,
Andrew Lunn <andrew@...n.ch>,
Vivien Didelot <vivien.didelot@...il.com>
Cc: martin.kaistra@...utronix.de,
Richard Cochran <richardcochran@...il.com>,
Vladimir Oltean <olteanv@...il.com>,
"David S. Miller" <davem@...emloft.net>,
Jakub Kicinski <kuba@...nel.org>,
John Stultz <john.stultz@...aro.org>,
Thomas Gleixner <tglx@...utronix.de>,
Stephen Boyd <sboyd@...nel.org>,
Russell King <linux@...linux.org.uk>,
Marc Kleine-Budde <mkl@...gutronix.de>,
linux-kernel@...r.kernel.org, netdev@...r.kernel.org
Subject: [PATCH 3/7] timecounter: allow for non-power of two overflow
Some hardware counters which are used as clocks have an overflow point
which is not a power of two. In order to be able to use the cycle
counter infrastructure with such hardware, add support for more generic
overflow logic.
Signed-off-by: Martin Kaistra <martin.kaistra@...utronix.de>
---
include/linux/timecounter.h | 3 +++
kernel/time/timecounter.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h
index c6540ceea143..c71196a742b3 100644
--- a/include/linux/timecounter.h
+++ b/include/linux/timecounter.h
@@ -26,12 +26,15 @@
* see CYCLECOUNTER_MASK() helper macro
* @mult: cycle to nanosecond multiplier
* @shift: cycle to nanosecond divisor (power of two)
+ * @overflow_point: non-power of two overflow point (optional),
+ * smaller than mask
*/
struct cyclecounter {
u64 (*read)(const struct cyclecounter *cc);
u64 mask;
u32 mult;
u32 shift;
+ u64 overflow_point;
};
/**
diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c
index e6285288d765..afd2910a9724 100644
--- a/kernel/time/timecounter.c
+++ b/kernel/time/timecounter.c
@@ -39,6 +39,9 @@ static u64 timecounter_read_delta(struct timecounter *tc)
/* calculate the delta since the last timecounter_read_delta(): */
cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
+ if (tc->cc->overflow_point && (cycle_now - tc->cycle_last) > tc->cc->mask)
+ cycle_delta -= tc->cc->mask - tc->cc->overflow_point;
+
/* convert to nanoseconds: */
ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
tc->mask, &tc->frac);
--
2.20.1
Powered by blists - more mailing lists