clock.c revision 178367
1/*- 2 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3 * Copyright (C) 1995, 1996 TooLs GmbH. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by TooLs GmbH. 17 * 4. The name of TooLs GmbH may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $ 32 */ 33/* 34 * Copyright (C) 2001 Benno Rice. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58#include <sys/cdefs.h> 59__FBSDID("$FreeBSD: head/sys/powerpc/aim/clock.c 178367 2008-04-21 04:41:37Z marcel $"); 60 61#include <sys/param.h> 62#include <sys/systm.h> 63#include <sys/kernel.h> 64#include <sys/sysctl.h> 65#include <sys/bus.h> 66#include <sys/clock.h> 67#include <sys/timetc.h> 68#include <sys/interrupt.h> 69 70#include <dev/ofw/openfirm.h> 71 72#include <machine/clock.h> 73#include <machine/cpu.h> 74#include <machine/intr.h> 75#include <machine/md_var.h> 76 77/* 78 * Initially we assume a processor with a bus frequency of 12.5 MHz. 79 */ 80u_int tickspending; 81u_long ns_per_tick = 80; 82static u_long ticks_per_sec = 12500000; 83static long ticks_per_intr; 84static volatile u_long lasttb; 85 86static timecounter_get_t decr_get_timecount; 87 88static struct timecounter decr_timecounter = { 89 decr_get_timecount, /* get_timecount */ 90 0, /* no poll_pps */ 91 ~0u, /* counter_mask */ 92 0, /* frequency */ 93 "decrementer" /* name */ 94}; 95 96void 97decr_intr(struct trapframe *frame) 98{ 99 u_long tb; 100 long tick; 101 int nticks; 102 103 /* 104 * Check whether we are initialized. 105 */ 106 if (!ticks_per_intr) 107 return; 108 109 /* 110 * Based on the actual time delay since the last decrementer reload, 111 * we arrange for earlier interrupt next time. 112 */ 113 __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick)); 114 for (nticks = 0; tick < 0; nticks++) 115 tick += ticks_per_intr; 116 mtdec(tick); 117 /* 118 * lasttb is used during microtime. Set it to the virtual 119 * start of this tick interval. 120 */ 121 lasttb = tb + tick - ticks_per_intr; 122 123 nticks += tickspending; 124 tickspending = 0; 125 126 /* 127 * Reenable interrupts 128 */ 129#if 0 130 msr = mfmsr(); 131 mtmsr(msr | PSL_EE | PSL_RI); 132#endif 133 /* 134 * Do standard timer interrupt stuff. 135 * Do softclock stuff only on the last iteration. 136 */ 137#if 0 138 while (--nticks > 0) { 139 hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); 140 } 141#endif 142 hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); 143} 144 145void 146decr_init(void) 147{ 148 int qhandle, phandle; 149 char name[32]; 150 unsigned int msr; 151 152 phandle = 0; 153 154 /* 155 * Get this info during autoconf? XXX 156 */ 157 for (qhandle = OF_peer(0); qhandle; qhandle = phandle) { 158 if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0 159 && !strcmp(name, "cpu") 160 && OF_getprop(qhandle, "timebase-frequency", 161 &ticks_per_sec, sizeof ticks_per_sec) >= 0) { 162 /* 163 * Should check for correct CPU here? XXX 164 */ 165 msr = mfmsr(); 166 mtmsr(msr & ~(PSL_EE|PSL_RI)); 167 168 ns_per_tick = 1000000000 / ticks_per_sec; 169 ticks_per_intr = ticks_per_sec / hz; 170 __asm __volatile ("mftb %0" : "=r"(lasttb)); 171 mtdec(ticks_per_intr); 172 173 mtmsr(msr); 174 175 break; 176 } 177 if ((phandle = OF_child(qhandle))) 178 continue; 179 while (qhandle) { 180 if ((phandle = OF_peer(qhandle))) 181 break; 182 qhandle = OF_parent(qhandle); 183 } 184 } 185 if (!phandle) 186 panic("no cpu node"); 187} 188 189void 190decr_tc_init(void) 191{ 192 decr_timecounter.tc_frequency = ticks_per_sec; 193 tc_init(&decr_timecounter); 194} 195 196static __inline u_quad_t 197mftb(void) 198{ 199 u_long scratch; 200 u_quad_t tb; 201 202 __asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b" 203 : "=r"(tb), "=r"(scratch)); 204 return tb; 205} 206 207static unsigned 208decr_get_timecount(struct timecounter *tc) 209{ 210 return mftb(); 211} 212 213/* 214 * Wait for about n microseconds (at least!). 215 */ 216void 217DELAY(int n) 218{ 219 u_quad_t tb, ttb; 220 221 tb = mftb(); 222 ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick; 223 while (tb < ttb) 224 tb = mftb(); 225} 226 227/* 228 * Nothing to do. 229 */ 230void 231cpu_startprofclock(void) 232{ 233 234 /* Do nothing */ 235} 236 237void 238cpu_stopprofclock(void) 239{ 240} 241