Tue Mar 18 14:34:31 2014 UTC ()
split 601 and generic PowerPC timecounter code a bit more


(macallan)
diff -r1.14 -r1.15 src/sys/arch/powerpc/powerpc/clock.c

cvs diff -r1.14 -r1.15 src/sys/arch/powerpc/powerpc/clock.c (expand / switch to unified diff)

--- src/sys/arch/powerpc/powerpc/clock.c 2014/03/03 15:36:36 1.14
+++ src/sys/arch/powerpc/powerpc/clock.c 2014/03/18 14:34:31 1.15
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: clock.c,v 1.14 2014/03/03 15:36:36 macallan Exp $ */ 1/* $NetBSD: clock.c,v 1.15 2014/03/18 14:34:31 macallan Exp $ */
2/* $OpenBSD: clock.c,v 1.3 1997/10/13 13:42:53 pefo Exp $ */ 2/* $OpenBSD: clock.c,v 1.3 1997/10/13 13:42:53 pefo Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * Copyright (C) 1995, 1996 TooLs GmbH.
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -23,66 +23,78 @@ @@ -23,66 +23,78 @@
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.14 2014/03/03 15:36:36 macallan Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.15 2014/03/18 14:34:31 macallan Exp $");
37 37
38#include <sys/param.h> 38#include <sys/param.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/systm.h> 40#include <sys/systm.h>
41#include <sys/device.h> 41#include <sys/device.h>
42#include <sys/timetc.h> 42#include <sys/timetc.h>
43 43
44#include <uvm/uvm_extern.h> 44#include <uvm/uvm_extern.h>
45 45
46#include <powerpc/psl.h> 46#include <powerpc/psl.h>
47#include <powerpc/spr.h> 47#include <powerpc/spr.h>
48#if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 48#if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
49#include <powerpc/oea/spr.h> 49#include <powerpc/oea/spr.h>
50#elif defined (PPC_BOOKE) 50#elif defined (PPC_BOOKE)
51#include <powerpc/booke/spr.h> 51#include <powerpc/booke/spr.h>
52#elif defined (PPC_IBM4XX) 52#elif defined (PPC_IBM4XX)
53#include <powerpc/ibm4xx/spr.h> 53#include <powerpc/ibm4xx/spr.h>
54#else 54#else
55#error unknown powerpc variant 55#error unknown powerpc variant
56#endif 56#endif
57 57
58void decr_intr(struct clockframe *); 58void decr_intr(struct clockframe *);
59void init_powerpc_tc(void); 59void init_powerpc_tc(void);
60static u_int get_powerpc_timecount(struct timecounter *); 60static u_int get_powerpc_timecount(struct timecounter *);
 61#ifdef PPC_OEA601
 62static u_int get_601_timecount(struct timecounter *);
 63#endif
61 64
62uint32_t ticks_per_sec; 65uint32_t ticks_per_sec;
63uint32_t ns_per_tick; 66uint32_t ns_per_tick;
64uint32_t ticks_per_intr = 0; 67uint32_t ticks_per_intr = 0;
65 68
 69#ifdef PPC_OEA601
 70static struct timecounter powerpc_601_timecounter = {
 71 get_601_timecount, /* get_timecount */
 72 0, /* no poll_pps */
 73 0x7fffffff, /* counter_mask */
 74 0, /* frequency */
 75 "rtc", /* name */
 76 100, /* quality */
 77 NULL, /* tc_priv */
 78 NULL /* tc_next */
 79};
 80#endif
 81
66static struct timecounter powerpc_timecounter = { 82static struct timecounter powerpc_timecounter = {
67 get_powerpc_timecount, /* get_timecount */ 83 get_powerpc_timecount, /* get_timecount */
68 0, /* no poll_pps */ 84 0, /* no poll_pps */
69 0x7fffffff, /* counter_mask */ 85 0x7fffffff, /* counter_mask */
70 0, /* frequency */ 86 0, /* frequency */
71#if PPC_OEA601 
72 "rtc", /* name */ 
73#else 
74 "mftb", /* name */ 87 "mftb", /* name */
75#endif 
76 100, /* quality */ 88 100, /* quality */
77 NULL, /* tc_priv */ 89 NULL, /* tc_priv */
78 NULL /* tc_next */ 90 NULL /* tc_next */
79}; 91};
80 92
81/* 93/*
82 * Start the real-time and statistics clocks. Leave stathz 0 since there 94 * Start the real-time and statistics clocks. Leave stathz 0 since there
83 * are no other timers available. 95 * are no other timers available.
84 */ 96 */
85void 97void
86cpu_initclocks(void) 98cpu_initclocks(void)
87{ 99{
88 struct cpu_info * const ci = curcpu(); 100 struct cpu_info * const ci = curcpu();
@@ -112,27 +124,27 @@ cpu_initclocks(void) @@ -112,27 +124,27 @@ cpu_initclocks(void)
112 * but that would be a drag. 124 * but that would be a drag.
113 */ 125 */
114void 126void
115setstatclockrate(int arg) 127setstatclockrate(int arg)
116{ 128{
117 129
118 /* Nothing we can do */ 130 /* Nothing we can do */
119} 131}
120 132
121void 133void
122decr_intr(struct clockframe *cfp) 134decr_intr(struct clockframe *cfp)
123{ 135{
124 struct cpu_info * const ci = curcpu(); 136 struct cpu_info * const ci = curcpu();
125 int msr; 137 const register_t msr = mfmsr();
126 int pri; 138 int pri;
127 u_long tb; 139 u_long tb;
128 long ticks; 140 long ticks;
129 int nticks; 141 int nticks;
130 142
131 /* Check whether we are initialized */ 143 /* Check whether we are initialized */
132 if (!ticks_per_intr) 144 if (!ticks_per_intr)
133 return; 145 return;
134 146
135 /* 147 /*
136 * Based on the actual time delay since the last decrementer reload, 148 * Based on the actual time delay since the last decrementer reload,
137 * we arrange for earlier interrupt next time. 149 * we arrange for earlier interrupt next time.
138 */ 150 */
@@ -153,42 +165,41 @@ decr_intr(struct clockframe *cfp) @@ -153,42 +165,41 @@ decr_intr(struct clockframe *cfp)
153 165
154 /* 166 /*
155 * lasttb is used during microtime. Set it to the virtual 167 * lasttb is used during microtime. Set it to the virtual
156 * start of this tick interval. 168 * start of this tick interval.
157 */ 169 */
158#ifdef PPC_OEA601 170#ifdef PPC_OEA601
159 if ((mfpvr() >> 16) == MPC601) 171 if ((mfpvr() >> 16) == MPC601)
160 tb = rtc_nanosecs(); 172 tb = rtc_nanosecs();
161 else 173 else
162#endif 174#endif
163 __asm volatile ("mftb %0" : "=r"(tb)); 175 __asm volatile ("mftb %0" : "=r"(tb));
164 176
165 ci->ci_lasttb = tb + ticks - ticks_per_intr; 177 ci->ci_lasttb = tb + ticks - ticks_per_intr;
166 178 ci->ci_idepth++;
167 /* 179 mtmsr(msr | PSL_EE);
168 * Reenable interrupts 
169 */ 
170 __asm volatile ("mfmsr %0; ori %0, %0, %1; mtmsr %0" 
171 : "=r"(msr) : "K"(PSL_EE)); 
172 
173 /* 180 /*
174 * Do standard timer interrupt stuff. 181 * Do standard timer interrupt stuff.
175 * Do softclock stuff only on the last iteration. 182 * Do softclock stuff only on the last iteration.
176 */ 183 */
177 while (--nticks > 0) 184 while (--nticks > 0)
178 hardclock(cfp); 185 hardclock(cfp);
179 hardclock(cfp); 186 hardclock(cfp);
 187 mtmsr(msr);
 188 ci->ci_idepth--;
180 } 189 }
 190 mtmsr(msr | PSL_EE);
181 splx(pri); 191 splx(pri);
 192 mtmsr(msr);
182} 193}
183 194
184/* 195/*
185 * Wait for about n microseconds (at least!). 196 * Wait for about n microseconds (at least!).
186 */ 197 */
187void 198void
188delay(unsigned int n) 199delay(unsigned int n)
189{ 200{
190#ifdef _ARCH_PPC64 201#ifdef _ARCH_PPC64
191 uint64_t tb, scratch; 202 uint64_t tb, scratch;
192#else 203#else
193 uint64_t tb; 204 uint64_t tb;
194 uint32_t tbh, tbl, scratch; 205 uint32_t tbh, tbl, scratch;
@@ -231,31 +242,52 @@ delay(unsigned int n) @@ -231,31 +242,52 @@ delay(unsigned int n)
231 : "cr0"); 242 : "cr0");
232#endif 243#endif
233 } 244 }
234} 245}
235 246
236static u_int 247static u_int
237get_powerpc_timecount(struct timecounter *tc) 248get_powerpc_timecount(struct timecounter *tc)
238{ 249{
239 u_long tb; 250 u_long tb;
240 int msr, scratch; 251 int msr, scratch;
241  252
242 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 253 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1"
243 : "=r"(msr), "=r"(scratch) : "K"((u_short)~PSL_EE)); 254 : "=r"(msr), "=r"(scratch) : "K"((u_short)~PSL_EE));
 255
 256 tb = (u_int)(mftb() & 0x7fffffff);
 257 mtmsr(msr);
 258
 259 return tb;
 260}
 261
244#ifdef PPC_OEA601 262#ifdef PPC_OEA601
245 if ((mfpvr() >> 16) == MPC601) 263static u_int
246 tb = rtc_nanosecs(); 264get_601_timecount(struct timecounter *tc)
247 else 265{
248#endif 266 u_long tb;
249 __asm volatile ("mftb %0" : "=r"(tb)); 267 int msr, scratch;
 268
 269 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1"
 270 : "=r"(msr), "=r"(scratch) : "K"((u_short)~PSL_EE));
 271
 272 tb = rtc_nanosecs();
250 mtmsr(msr); 273 mtmsr(msr);
251 274
252 return tb; 275 return tb;
253} 276}
 277#endif
254 278
255void 279void
256init_powerpc_tc(void) 280init_powerpc_tc(void)
257{ 281{
258 /* from machdep initialization */ 282 struct timecounter *tc;
259 powerpc_timecounter.tc_frequency = ticks_per_sec; 283
260 tc_init(&powerpc_timecounter); 284#ifdef PPC_OEA601
 285 if ((mfpvr() >> 16) == MPC601) {
 286 tc = &powerpc_601_timecounter;
 287 } else
 288#endif
 289 tc = &powerpc_timecounter;
 290
 291 tc->tc_frequency = ticks_per_sec;
 292 tc_init(tc);
261} 293}