1 /* 1 2 * OR1K timer synchronisation 3 * 4 * Based on work from MIPS implementation. 5 * 6 * All CPUs will have their count registers sy 7 * value. This can cause a small timewarp for 8 * not have done anything significant (but the 9 * enabled briefly - prom_smp_finish() should 10 * interrupts...) 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/irqflags.h> 15 #include <linux/cpumask.h> 16 17 #include <asm/time.h> 18 #include <asm/timex.h> 19 #include <linux/atomic.h> 20 #include <asm/barrier.h> 21 22 #include <asm/spr.h> 23 24 static unsigned int initcount; 25 static atomic_t count_count_start = ATOMIC_INI 26 static atomic_t count_count_stop = ATOMIC_INIT 27 28 #define COUNTON 100 29 #define NR_LOOPS 3 30 31 void synchronise_count_master(int cpu) 32 { 33 int i; 34 unsigned long flags; 35 36 pr_info("Synchronize counters for CPU 37 38 local_irq_save(flags); 39 40 /* 41 * We loop a few times to get a primed 42 * then the last pass is more or less 43 * the master and slaves each set thei 44 * value all at once. This reduces the 45 * between the processors, and guarant 46 * delay between the cycle counters is 47 * the latency of information-passing 48 * two CPUs. 49 */ 50 51 for (i = 0; i < NR_LOOPS; i++) { 52 /* slaves loop on '!= 2' */ 53 while (atomic_read(&count_coun 54 mb(); 55 atomic_set(&count_count_stop, 56 smp_wmb(); 57 58 /* Let the slave writes its co 59 atomic_inc(&count_count_start) 60 61 /* Count will be initialised t 62 if (i == 1) 63 initcount = get_cycles 64 65 /* 66 * Everyone initialises count 67 */ 68 if (i == NR_LOOPS-1) 69 openrisc_timer_set(ini 70 71 /* 72 * Wait for slave to leave the 73 */ 74 while (atomic_read(&count_coun 75 mb(); 76 atomic_set(&count_count_start, 77 smp_wmb(); 78 atomic_inc(&count_count_stop); 79 } 80 /* Arrange for an interrupt in a short 81 openrisc_timer_set_next(COUNTON); 82 83 local_irq_restore(flags); 84 85 /* 86 * i386 code reported the skew here, b 87 * count registers were almost certain 88 * so no point in alarming people 89 */ 90 pr_cont("done.\n"); 91 } 92 93 void synchronise_count_slave(int cpu) 94 { 95 int i; 96 97 /* 98 * Not every cpu is online at the time 99 * so we first wait for the master to 100 */ 101 102 for (i = 0; i < NR_LOOPS; i++) { 103 atomic_inc(&count_count_start) 104 while (atomic_read(&count_coun 105 mb(); 106 107 /* 108 * Everyone initialises count 109 */ 110 if (i == NR_LOOPS-1) 111 openrisc_timer_set(ini 112 113 atomic_inc(&count_count_stop); 114 while (atomic_read(&count_coun 115 mb(); 116 } 117 /* Arrange for an interrupt in a short 118 openrisc_timer_set_next(COUNTON); 119 } 120 #undef NR_LOOPS 121
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.