1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2001 MontaVista Software Inc. 4 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 5 * Copyright (c) 2003, 2004 Maciej W. Rozycki 6 * 7 * Common time service routines for MIPS machines. 8 */ 9 #include <linux/bug.h> 10 #include <linux/clockchips.h> 11 #include <linux/types.h> 12 #include <linux/kernel.h> 13 #include <linux/init.h> 14 #include <linux/sched.h> 15 #include <linux/param.h> 16 #include <linux/time.h> 17 #include <linux/timex.h> 18 #include <linux/smp.h> 19 #include <linux/spinlock.h> 20 #include <linux/export.h> 21 #include <linux/cpufreq.h> 22 #include <linux/delay.h> 23 24 #include <asm/cpu-features.h> 25 #include <asm/cpu-type.h> 26 #include <asm/div64.h> 27 #include <asm/time.h> 28 29 #ifdef CONFIG_CPU_FREQ 30 31 static DEFINE_PER_CPU(unsigned long, pcp_lpj_ref); 32 static DEFINE_PER_CPU(unsigned long, pcp_lpj_ref_freq); 33 static unsigned long glb_lpj_ref; 34 static unsigned long glb_lpj_ref_freq; 35 36 static int cpufreq_callback(struct notifier_block *nb, 37 unsigned long val, void *data) 38 { 39 struct cpufreq_freqs *freq = data; 40 struct cpumask *cpus = freq->policy->cpus; 41 unsigned long lpj; 42 int cpu; 43 44 /* 45 * Skip lpj numbers adjustment if the CPU-freq transition is safe for 46 * the loops delay. (Is this possible?) 47 */ 48 if (freq->flags & CPUFREQ_CONST_LOOPS) 49 return NOTIFY_OK; 50 51 /* Save the initial values of the lpjes for future scaling. */ 52 if (!glb_lpj_ref) { 53 glb_lpj_ref = boot_cpu_data.udelay_val; 54 glb_lpj_ref_freq = freq->old; 55 56 for_each_online_cpu(cpu) { 57 per_cpu(pcp_lpj_ref, cpu) = 58 cpu_data[cpu].udelay_val; 59 per_cpu(pcp_lpj_ref_freq, cpu) = freq->old; 60 } 61 } 62 63 /* 64 * Adjust global lpj variable and per-CPU udelay_val number in 65 * accordance with the new CPU frequency. 66 */ 67 if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || 68 (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { 69 loops_per_jiffy = cpufreq_scale(glb_lpj_ref, 70 glb_lpj_ref_freq, 71 freq->new); 72 73 for_each_cpu(cpu, cpus) { 74 lpj = cpufreq_scale(per_cpu(pcp_lpj_ref, cpu), 75 per_cpu(pcp_lpj_ref_freq, cpu), 76 freq->new); 77 cpu_data[cpu].udelay_val = (unsigned int)lpj; 78 } 79 } 80 81 return NOTIFY_OK; 82 } 83 84 static struct notifier_block cpufreq_notifier = { 85 .notifier_call = cpufreq_callback, 86 }; 87 88 static int __init register_cpufreq_notifier(void) 89 { 90 return cpufreq_register_notifier(&cpufreq_notifier, 91 CPUFREQ_TRANSITION_NOTIFIER); 92 } 93 core_initcall(register_cpufreq_notifier); 94 95 #endif /* CONFIG_CPU_FREQ */ 96 97 /* 98 * forward reference 99 */ 100 DEFINE_SPINLOCK(rtc_lock); 101 EXPORT_SYMBOL(rtc_lock); 102 103 static int null_perf_irq(void) 104 { 105 return 0; 106 } 107 108 int (*perf_irq)(void) = null_perf_irq; 109 110 EXPORT_SYMBOL(perf_irq); 111 112 /* 113 * time_init() - it does the following things. 114 * 115 * 1) plat_time_init() - 116 * a) (optional) set up RTC routines, 117 * b) (optional) calibrate and set the mips_hpt_frequency 118 * (only needed if you intended to use cpu counter as timer interrupt 119 * source) 120 * 2) calculate a couple of cached variables for later usage 121 */ 122 123 unsigned int mips_hpt_frequency; 124 EXPORT_SYMBOL_GPL(mips_hpt_frequency); 125 126 static __init int cpu_has_mfc0_count_bug(void) 127 { 128 switch (current_cpu_type()) { 129 case CPU_R4000PC: 130 case CPU_R4000SC: 131 case CPU_R4000MC: 132 /* 133 * V3.0 is documented as suffering from the mfc0 from count bug. 134 * Afaik this is the last version of the R4000. Later versions 135 * were marketed as R4400. 136 */ 137 return 1; 138 139 case CPU_R4400PC: 140 case CPU_R4400SC: 141 case CPU_R4400MC: 142 /* 143 * The published errata for the R4400 up to 3.0 say the CPU 144 * has the mfc0 from count bug. This seems the last version 145 * produced. 146 */ 147 return 1; 148 } 149 150 return 0; 151 } 152 153 void __init time_init(void) 154 { 155 plat_time_init(); 156 157 /* 158 * The use of the R4k timer as a clock event takes precedence; 159 * if reading the Count register might interfere with the timer 160 * interrupt, then we don't use the timer as a clock source. 161 * We may still use the timer as a clock source though if the 162 * timer interrupt isn't reliable; the interference doesn't 163 * matter then, because we don't use the interrupt. 164 */ 165 if (mips_clockevent_init() != 0 || !cpu_has_mfc0_count_bug()) 166 init_mips_clocksource(); 167 } 168
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.