1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* 3 * Copyright 2001 MontaVista Software Inc. 4 * Author: Jun Sun, jsun@mvista.com or jsun@ju 5 * Copyright (c) 2003, 2004 Maciej W. Rozycki 6 * 7 * Common time service routines for MIPS machi 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_r 32 static DEFINE_PER_CPU(unsigned long, pcp_lpj_r 33 static unsigned long glb_lpj_ref; 34 static unsigned long glb_lpj_ref_freq; 35 36 static int cpufreq_callback(struct notifier_bl 37 unsigned long val, 38 { 39 struct cpufreq_freqs *freq = data; 40 struct cpumask *cpus = freq->policy->c 41 unsigned long lpj; 42 int cpu; 43 44 /* 45 * Skip lpj numbers adjustment if the 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 lpje 52 if (!glb_lpj_ref) { 53 glb_lpj_ref = boot_cpu_data.ud 54 glb_lpj_ref_freq = freq->old; 55 56 for_each_online_cpu(cpu) { 57 per_cpu(pcp_lpj_ref, c 58 cpu_data[cpu]. 59 per_cpu(pcp_lpj_ref_fr 60 } 61 } 62 63 /* 64 * Adjust global lpj variable and per- 65 * accordance with the new CPU frequen 66 */ 67 if ((val == CPUFREQ_PRECHANGE && freq 68 (val == CPUFREQ_POSTCHANGE && freq 69 loops_per_jiffy = cpufreq_scal 70 71 72 73 for_each_cpu(cpu, cpus) { 74 lpj = cpufreq_scale(pe 75 pe 76 fr 77 cpu_data[cpu].udelay_v 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(vo 89 { 90 return cpufreq_register_notifier(&cpuf 91 CPUFR 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 mi 118 * (only needed if you intended to us 119 * source) 120 * 2) calculate a couple of cached variables f 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 suffe 134 * Afaik this is the last vers 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 th 144 * has the mfc0 from count bug 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 159 * if reading the Count register might 160 * interrupt, then we don't use the ti 161 * We may still use the timer as a clo 162 * timer interrupt isn't reliable; the 163 * matter then, because we don't use t 164 */ 165 if (mips_clockevent_init() != 0 || !cp 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.