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 22 #include <asm/cpu-features.h> 23 #include <asm/cpu-type.h> 24 #include <asm/div64.h> 25 #include <asm/time.h> 26 27 /* 28 * forward reference 29 */ 30 DEFINE_SPINLOCK(rtc_lock); 31 EXPORT_SYMBOL(rtc_lock); 32 33 static int null_perf_irq(void) 34 { 35 return 0; 36 } 37 38 int (*perf_irq)(void) = null_perf_irq; 39 40 EXPORT_SYMBOL(perf_irq); 41 42 /* 43 * time_init() - it does the following things. 44 * 45 * 1) plat_time_init() - 46 * a) (optional) set up RTC routines, 47 * b) (optional) calibrate and set the mips_hpt_frequency 48 * (only needed if you intended to use cpu counter as timer interrupt 49 * source) 50 * 2) calculate a couple of cached variables for later usage 51 */ 52 53 unsigned int mips_hpt_frequency; 54 EXPORT_SYMBOL_GPL(mips_hpt_frequency); 55 56 static __init int cpu_has_mfc0_count_bug(void) 57 { 58 switch (current_cpu_type()) { 59 case CPU_R4000PC: 60 case CPU_R4000SC: 61 case CPU_R4000MC: 62 /* 63 * V3.0 is documented as suffering from the mfc0 from count bug. 64 * Afaik this is the last version of the R4000. Later versions 65 * were marketed as R4400. 66 */ 67 return 1; 68 69 case CPU_R4400PC: 70 case CPU_R4400SC: 71 case CPU_R4400MC: 72 /* 73 * The published errata for the R4400 up to 3.0 say the CPU 74 * has the mfc0 from count bug. 75 */ 76 if ((current_cpu_data.processor_id & 0xff) <= 0x30) 77 return 1; 78 79 /* 80 * we assume newer revisions are ok 81 */ 82 return 0; 83 } 84 85 return 0; 86 } 87 88 void __init time_init(void) 89 { 90 plat_time_init(); 91 92 /* 93 * The use of the R4k timer as a clock event takes precedence; 94 * if reading the Count register might interfere with the timer 95 * interrupt, then we don't use the timer as a clock source. 96 * We may still use the timer as a clock source though if the 97 * timer interrupt isn't reliable; the interference doesn't 98 * matter then, because we don't use the interrupt. 99 */ 100 if (mips_clockevent_init() != 0 || !cpu_has_mfc0_count_bug()) 101 init_mips_clocksource(); 102 } 103