18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* calibrate.c: default delay calibration 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Excised from init/main.c 58c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 98c2ecf20Sopenharmony_ci#include <linux/delay.h> 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/timex.h> 128c2ecf20Sopenharmony_ci#include <linux/smp.h> 138c2ecf20Sopenharmony_ci#include <linux/percpu.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ciunsigned long lpj_fine; 168c2ecf20Sopenharmony_ciunsigned long preset_lpj; 178c2ecf20Sopenharmony_cistatic int __init lpj_setup(char *str) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci preset_lpj = simple_strtoul(str,NULL,0); 208c2ecf20Sopenharmony_ci return 1; 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci__setup("lpj=", lpj_setup); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#ifdef ARCH_HAS_READ_CURRENT_TIMER 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* This routine uses the read_current_timer() routine and gets the 288c2ecf20Sopenharmony_ci * loops per jiffy directly, instead of guessing it using delay(). 298c2ecf20Sopenharmony_ci * Also, this code tries to handle non-maskable asynchronous events 308c2ecf20Sopenharmony_ci * (like SMIs) 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci#define DELAY_CALIBRATION_TICKS ((HZ < 100) ? 1 : (HZ/100)) 338c2ecf20Sopenharmony_ci#define MAX_DIRECT_CALIBRATION_RETRIES 5 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic unsigned long calibrate_delay_direct(void) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci unsigned long pre_start, start, post_start; 388c2ecf20Sopenharmony_ci unsigned long pre_end, end, post_end; 398c2ecf20Sopenharmony_ci unsigned long start_jiffies; 408c2ecf20Sopenharmony_ci unsigned long timer_rate_min, timer_rate_max; 418c2ecf20Sopenharmony_ci unsigned long good_timer_sum = 0; 428c2ecf20Sopenharmony_ci unsigned long good_timer_count = 0; 438c2ecf20Sopenharmony_ci unsigned long measured_times[MAX_DIRECT_CALIBRATION_RETRIES]; 448c2ecf20Sopenharmony_ci int max = -1; /* index of measured_times with max/min values or not set */ 458c2ecf20Sopenharmony_ci int min = -1; 468c2ecf20Sopenharmony_ci int i; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (read_current_timer(&pre_start) < 0 ) 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* 528c2ecf20Sopenharmony_ci * A simple loop like 538c2ecf20Sopenharmony_ci * while ( jiffies < start_jiffies+1) 548c2ecf20Sopenharmony_ci * start = read_current_timer(); 558c2ecf20Sopenharmony_ci * will not do. As we don't really know whether jiffy switch 568c2ecf20Sopenharmony_ci * happened first or timer_value was read first. And some asynchronous 578c2ecf20Sopenharmony_ci * event can happen between these two events introducing errors in lpj. 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * So, we do 608c2ecf20Sopenharmony_ci * 1. pre_start <- When we are sure that jiffy switch hasn't happened 618c2ecf20Sopenharmony_ci * 2. check jiffy switch 628c2ecf20Sopenharmony_ci * 3. start <- timer value before or after jiffy switch 638c2ecf20Sopenharmony_ci * 4. post_start <- When we are sure that jiffy switch has happened 648c2ecf20Sopenharmony_ci * 658c2ecf20Sopenharmony_ci * Note, we don't know anything about order of 2 and 3. 668c2ecf20Sopenharmony_ci * Now, by looking at post_start and pre_start difference, we can 678c2ecf20Sopenharmony_ci * check whether any asynchronous event happened or not 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) { 718c2ecf20Sopenharmony_ci pre_start = 0; 728c2ecf20Sopenharmony_ci read_current_timer(&start); 738c2ecf20Sopenharmony_ci start_jiffies = jiffies; 748c2ecf20Sopenharmony_ci while (time_before_eq(jiffies, start_jiffies + 1)) { 758c2ecf20Sopenharmony_ci pre_start = start; 768c2ecf20Sopenharmony_ci read_current_timer(&start); 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci read_current_timer(&post_start); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci pre_end = 0; 818c2ecf20Sopenharmony_ci end = post_start; 828c2ecf20Sopenharmony_ci while (time_before_eq(jiffies, start_jiffies + 1 + 838c2ecf20Sopenharmony_ci DELAY_CALIBRATION_TICKS)) { 848c2ecf20Sopenharmony_ci pre_end = end; 858c2ecf20Sopenharmony_ci read_current_timer(&end); 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci read_current_timer(&post_end); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci timer_rate_max = (post_end - pre_start) / 908c2ecf20Sopenharmony_ci DELAY_CALIBRATION_TICKS; 918c2ecf20Sopenharmony_ci timer_rate_min = (pre_end - post_start) / 928c2ecf20Sopenharmony_ci DELAY_CALIBRATION_TICKS; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* 958c2ecf20Sopenharmony_ci * If the upper limit and lower limit of the timer_rate is 968c2ecf20Sopenharmony_ci * >= 12.5% apart, redo calibration. 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci if (start >= post_end) 998c2ecf20Sopenharmony_ci printk(KERN_NOTICE "calibrate_delay_direct() ignoring " 1008c2ecf20Sopenharmony_ci "timer_rate as we had a TSC wrap around" 1018c2ecf20Sopenharmony_ci " start=%lu >=post_end=%lu\n", 1028c2ecf20Sopenharmony_ci start, post_end); 1038c2ecf20Sopenharmony_ci if (start < post_end && pre_start != 0 && pre_end != 0 && 1048c2ecf20Sopenharmony_ci (timer_rate_max - timer_rate_min) < (timer_rate_max >> 3)) { 1058c2ecf20Sopenharmony_ci good_timer_count++; 1068c2ecf20Sopenharmony_ci good_timer_sum += timer_rate_max; 1078c2ecf20Sopenharmony_ci measured_times[i] = timer_rate_max; 1088c2ecf20Sopenharmony_ci if (max < 0 || timer_rate_max > measured_times[max]) 1098c2ecf20Sopenharmony_ci max = i; 1108c2ecf20Sopenharmony_ci if (min < 0 || timer_rate_max < measured_times[min]) 1118c2ecf20Sopenharmony_ci min = i; 1128c2ecf20Sopenharmony_ci } else 1138c2ecf20Sopenharmony_ci measured_times[i] = 0; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* 1188c2ecf20Sopenharmony_ci * Find the maximum & minimum - if they differ too much throw out the 1198c2ecf20Sopenharmony_ci * one with the largest difference from the mean and try again... 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_ci while (good_timer_count > 1) { 1228c2ecf20Sopenharmony_ci unsigned long estimate; 1238c2ecf20Sopenharmony_ci unsigned long maxdiff; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* compute the estimate */ 1268c2ecf20Sopenharmony_ci estimate = (good_timer_sum/good_timer_count); 1278c2ecf20Sopenharmony_ci maxdiff = estimate >> 3; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* if range is within 12% let's take it */ 1308c2ecf20Sopenharmony_ci if ((measured_times[max] - measured_times[min]) < maxdiff) 1318c2ecf20Sopenharmony_ci return estimate; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* ok - drop the worse value and try again... */ 1348c2ecf20Sopenharmony_ci good_timer_sum = 0; 1358c2ecf20Sopenharmony_ci good_timer_count = 0; 1368c2ecf20Sopenharmony_ci if ((measured_times[max] - estimate) < 1378c2ecf20Sopenharmony_ci (estimate - measured_times[min])) { 1388c2ecf20Sopenharmony_ci printk(KERN_NOTICE "calibrate_delay_direct() dropping " 1398c2ecf20Sopenharmony_ci "min bogoMips estimate %d = %lu\n", 1408c2ecf20Sopenharmony_ci min, measured_times[min]); 1418c2ecf20Sopenharmony_ci measured_times[min] = 0; 1428c2ecf20Sopenharmony_ci min = max; 1438c2ecf20Sopenharmony_ci } else { 1448c2ecf20Sopenharmony_ci printk(KERN_NOTICE "calibrate_delay_direct() dropping " 1458c2ecf20Sopenharmony_ci "max bogoMips estimate %d = %lu\n", 1468c2ecf20Sopenharmony_ci max, measured_times[max]); 1478c2ecf20Sopenharmony_ci measured_times[max] = 0; 1488c2ecf20Sopenharmony_ci max = min; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) { 1528c2ecf20Sopenharmony_ci if (measured_times[i] == 0) 1538c2ecf20Sopenharmony_ci continue; 1548c2ecf20Sopenharmony_ci good_timer_count++; 1558c2ecf20Sopenharmony_ci good_timer_sum += measured_times[i]; 1568c2ecf20Sopenharmony_ci if (measured_times[i] < measured_times[min]) 1578c2ecf20Sopenharmony_ci min = i; 1588c2ecf20Sopenharmony_ci if (measured_times[i] > measured_times[max]) 1598c2ecf20Sopenharmony_ci max = i; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci printk(KERN_NOTICE "calibrate_delay_direct() failed to get a good " 1658c2ecf20Sopenharmony_ci "estimate for loops_per_jiffy.\nProbably due to long platform " 1668c2ecf20Sopenharmony_ci "interrupts. Consider using \"lpj=\" boot option.\n"); 1678c2ecf20Sopenharmony_ci return 0; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci#else 1708c2ecf20Sopenharmony_cistatic unsigned long calibrate_delay_direct(void) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci return 0; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci#endif 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci/* 1778c2ecf20Sopenharmony_ci * This is the number of bits of precision for the loops_per_jiffy. Each 1788c2ecf20Sopenharmony_ci * time we refine our estimate after the first takes 1.5/HZ seconds, so try 1798c2ecf20Sopenharmony_ci * to start with a good estimate. 1808c2ecf20Sopenharmony_ci * For the boot cpu we can skip the delay calibration and assign it a value 1818c2ecf20Sopenharmony_ci * calculated based on the timer frequency. 1828c2ecf20Sopenharmony_ci * For the rest of the CPUs we cannot assume that the timer frequency is same as 1838c2ecf20Sopenharmony_ci * the cpu frequency, hence do the calibration for those. 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci#define LPS_PREC 8 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic unsigned long calibrate_delay_converge(void) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci /* First stage - slowly accelerate to find initial bounds */ 1908c2ecf20Sopenharmony_ci unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit; 1918c2ecf20Sopenharmony_ci int trials = 0, band = 0, trial_in_band = 0; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci lpj = (1<<12); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci /* wait for "start of" clock tick */ 1968c2ecf20Sopenharmony_ci ticks = jiffies; 1978c2ecf20Sopenharmony_ci while (ticks == jiffies) 1988c2ecf20Sopenharmony_ci ; /* nothing */ 1998c2ecf20Sopenharmony_ci /* Go .. */ 2008c2ecf20Sopenharmony_ci ticks = jiffies; 2018c2ecf20Sopenharmony_ci do { 2028c2ecf20Sopenharmony_ci if (++trial_in_band == (1<<band)) { 2038c2ecf20Sopenharmony_ci ++band; 2048c2ecf20Sopenharmony_ci trial_in_band = 0; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci __delay(lpj * band); 2078c2ecf20Sopenharmony_ci trials += band; 2088c2ecf20Sopenharmony_ci } while (ticks == jiffies); 2098c2ecf20Sopenharmony_ci /* 2108c2ecf20Sopenharmony_ci * We overshot, so retreat to a clear underestimate. Then estimate 2118c2ecf20Sopenharmony_ci * the largest likely undershoot. This defines our chop bounds. 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_ci trials -= band; 2148c2ecf20Sopenharmony_ci loopadd_base = lpj * band; 2158c2ecf20Sopenharmony_ci lpj_base = lpj * trials; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cirecalibrate: 2188c2ecf20Sopenharmony_ci lpj = lpj_base; 2198c2ecf20Sopenharmony_ci loopadd = loopadd_base; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci /* 2228c2ecf20Sopenharmony_ci * Do a binary approximation to get lpj set to 2238c2ecf20Sopenharmony_ci * equal one clock (up to LPS_PREC bits) 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci chop_limit = lpj >> LPS_PREC; 2268c2ecf20Sopenharmony_ci while (loopadd > chop_limit) { 2278c2ecf20Sopenharmony_ci lpj += loopadd; 2288c2ecf20Sopenharmony_ci ticks = jiffies; 2298c2ecf20Sopenharmony_ci while (ticks == jiffies) 2308c2ecf20Sopenharmony_ci ; /* nothing */ 2318c2ecf20Sopenharmony_ci ticks = jiffies; 2328c2ecf20Sopenharmony_ci __delay(lpj); 2338c2ecf20Sopenharmony_ci if (jiffies != ticks) /* longer than 1 tick */ 2348c2ecf20Sopenharmony_ci lpj -= loopadd; 2358c2ecf20Sopenharmony_ci loopadd >>= 1; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci /* 2388c2ecf20Sopenharmony_ci * If we incremented every single time possible, presume we've 2398c2ecf20Sopenharmony_ci * massively underestimated initially, and retry with a higher 2408c2ecf20Sopenharmony_ci * start, and larger range. (Only seen on x86_64, due to SMIs) 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_ci if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) { 2438c2ecf20Sopenharmony_ci lpj_base = lpj; 2448c2ecf20Sopenharmony_ci loopadd_base <<= 2; 2458c2ecf20Sopenharmony_ci goto recalibrate; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci return lpj; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(unsigned long, cpu_loops_per_jiffy) = { 0 }; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci/* 2548c2ecf20Sopenharmony_ci * Check if cpu calibration delay is already known. For example, 2558c2ecf20Sopenharmony_ci * some processors with multi-core sockets may have all cores 2568c2ecf20Sopenharmony_ci * with the same calibration delay. 2578c2ecf20Sopenharmony_ci * 2588c2ecf20Sopenharmony_ci * Architectures should override this function if a faster calibration 2598c2ecf20Sopenharmony_ci * method is available. 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_ciunsigned long __attribute__((weak)) calibrate_delay_is_known(void) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci return 0; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci/* 2678c2ecf20Sopenharmony_ci * Indicate the cpu delay calibration is done. This can be used by 2688c2ecf20Sopenharmony_ci * architectures to stop accepting delay timer registrations after this point. 2698c2ecf20Sopenharmony_ci */ 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_civoid __attribute__((weak)) calibration_delay_done(void) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_civoid calibrate_delay(void) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci unsigned long lpj; 2788c2ecf20Sopenharmony_ci static bool printed; 2798c2ecf20Sopenharmony_ci int this_cpu = smp_processor_id(); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (per_cpu(cpu_loops_per_jiffy, this_cpu)) { 2828c2ecf20Sopenharmony_ci lpj = per_cpu(cpu_loops_per_jiffy, this_cpu); 2838c2ecf20Sopenharmony_ci if (!printed) 2848c2ecf20Sopenharmony_ci pr_info("Calibrating delay loop (skipped) " 2858c2ecf20Sopenharmony_ci "already calibrated this CPU"); 2868c2ecf20Sopenharmony_ci } else if (preset_lpj) { 2878c2ecf20Sopenharmony_ci lpj = preset_lpj; 2888c2ecf20Sopenharmony_ci if (!printed) 2898c2ecf20Sopenharmony_ci pr_info("Calibrating delay loop (skipped) " 2908c2ecf20Sopenharmony_ci "preset value.. "); 2918c2ecf20Sopenharmony_ci } else if ((!printed) && lpj_fine) { 2928c2ecf20Sopenharmony_ci lpj = lpj_fine; 2938c2ecf20Sopenharmony_ci pr_info("Calibrating delay loop (skipped), " 2948c2ecf20Sopenharmony_ci "value calculated using timer frequency.. "); 2958c2ecf20Sopenharmony_ci } else if ((lpj = calibrate_delay_is_known())) { 2968c2ecf20Sopenharmony_ci ; 2978c2ecf20Sopenharmony_ci } else if ((lpj = calibrate_delay_direct()) != 0) { 2988c2ecf20Sopenharmony_ci if (!printed) 2998c2ecf20Sopenharmony_ci pr_info("Calibrating delay using timer " 3008c2ecf20Sopenharmony_ci "specific routine.. "); 3018c2ecf20Sopenharmony_ci } else { 3028c2ecf20Sopenharmony_ci if (!printed) 3038c2ecf20Sopenharmony_ci pr_info("Calibrating delay loop... "); 3048c2ecf20Sopenharmony_ci lpj = calibrate_delay_converge(); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj; 3078c2ecf20Sopenharmony_ci if (!printed) 3088c2ecf20Sopenharmony_ci pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", 3098c2ecf20Sopenharmony_ci lpj/(500000/HZ), 3108c2ecf20Sopenharmony_ci (lpj/(5000/HZ)) % 100, lpj); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci loops_per_jiffy = lpj; 3138c2ecf20Sopenharmony_ci printed = true; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci calibration_delay_done(); 3168c2ecf20Sopenharmony_ci} 317