Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /* adjtimex() tick adjustment test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  *		by:   John Stultz <john.stultz@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *		(C) Copyright Linaro Limited 2015
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *		Licensed under the GPLv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  To build:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *	$ gcc adjtick.c -o adjtick -lrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *   This program is free software: you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *   it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *   the Free Software Foundation, either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *   (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *   This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *   GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <sys/timex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "../kselftest.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define CLOCK_MONOTONIC_RAW	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define NSEC_PER_SEC		1000000000LL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define USEC_PER_SEC		1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define MILLION			1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) long systick;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) long long llabs(long long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		val = -val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) unsigned long long ts_to_nsec(struct timespec ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) struct timespec nsec_to_ts(long long ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	struct timespec ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	ts.tv_sec = ns/NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	ts.tv_nsec = ns%NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	return ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) long long diff_timespec(struct timespec start, struct timespec end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	long long start_ns, end_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	start_ns = ts_to_nsec(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	end_ns = ts_to_nsec(end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	return end_ns - start_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) void get_monotonic_and_raw(struct timespec *mon, struct timespec *raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct timespec start, mid, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	long long diff = 0, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	clock_gettime(CLOCK_MONOTONIC, mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	clock_gettime(CLOCK_MONOTONIC_RAW, raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	/* Try to get a more tightly bound pairing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		long long newdiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		clock_gettime(CLOCK_MONOTONIC, &start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		clock_gettime(CLOCK_MONOTONIC_RAW, &mid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		clock_gettime(CLOCK_MONOTONIC, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		newdiff = diff_timespec(start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		if (diff == 0 || newdiff < diff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			diff = newdiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			*raw = mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			tmp = (ts_to_nsec(start) + ts_to_nsec(end))/2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			*mon = nsec_to_ts(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) long long get_ppm_drift(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct timespec mon_start, raw_start, mon_end, raw_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	long long delta1, delta2, eppm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	get_monotonic_and_raw(&mon_start, &raw_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	sleep(15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	get_monotonic_and_raw(&mon_end, &raw_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	delta1 = diff_timespec(mon_start, mon_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	delta2 = diff_timespec(raw_start, raw_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	eppm = (delta1*MILLION)/delta2 - MILLION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	return eppm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int check_tick_adj(long tickval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	long long eppm, ppm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	struct timex tx1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	tx1.modes	 = ADJ_TICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	tx1.modes	|= ADJ_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	tx1.modes	|= ADJ_FREQUENCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	tx1.modes	|= ADJ_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	tx1.status	= STA_PLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	tx1.offset	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	tx1.freq	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	tx1.tick	= tickval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	adjtimex(&tx1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	sleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	ppm = ((long long)tickval * MILLION)/systick - MILLION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	printf("Estimating tick (act: %ld usec, %lld ppm): ", tickval, ppm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	eppm = get_ppm_drift();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	printf("%lld usec, %lld ppm", systick + (systick * eppm / MILLION), eppm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	tx1.modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	adjtimex(&tx1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (tx1.offset || tx1.freq || tx1.tick != tickval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		printf("	[ERROR]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		printf("\tUnexpected adjtimex return values, make sure ntpd is not running.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	 * Here we use 100ppm difference as an error bound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	 * We likely should see better, but some coarse clocksources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	 * cannot match the HZ tick size accurately, so we have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	 * internal correction factor that doesn't scale exactly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	 * with the adjustment, resulting in > 10ppm error during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	 * a 10% adjustment. 100ppm also gives us more breathing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	 * room for interruptions during the measurement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (llabs(eppm - ppm) > 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		printf("	[FAILED]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	printf("	[OK]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return  0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int main(int argv, char **argc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	struct timespec raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	long tick, max, interval, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	struct timex tx1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	setbuf(stdout, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if (clock_gettime(CLOCK_MONOTONIC_RAW, &raw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		printf("ERR: NO CLOCK_MONOTONIC_RAW\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	printf("Each iteration takes about 15 seconds\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	systick = sysconf(_SC_CLK_TCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	systick = USEC_PER_SEC/sysconf(_SC_CLK_TCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	max = systick/10; /* +/- 10% */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	interval = max/4; /* in 4 steps each side */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	for (tick = (systick - max); tick < (systick + max); tick += interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		if (check_tick_adj(tick)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			err = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	/* Reset things to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	tx1.modes	 = ADJ_TICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	tx1.modes	|= ADJ_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	tx1.modes	|= ADJ_FREQUENCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	tx1.offset	 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	tx1.freq	 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	tx1.tick	 = systick;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	adjtimex(&tx1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		return ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	return ksft_exit_pass();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }