clock.c revision 198428
1285612Sdelphij/*-
2181834Sroberto * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3285612Sdelphij * Copyright (C) 1995, 1996 TooLs GmbH.
4285612Sdelphij * All rights reserved.
5285612Sdelphij *
6285612Sdelphij * Redistribution and use in source and binary forms, with or without
7285612Sdelphij * modification, are permitted provided that the following conditions
8285612Sdelphij * are met:
9285612Sdelphij * 1. Redistributions of source code must retain the above copyright
10285612Sdelphij *    notice, this list of conditions and the following disclaimer.
11285612Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
12285612Sdelphij *    notice, this list of conditions and the following disclaimer in the
13285612Sdelphij *    documentation and/or other materials provided with the distribution.
14285612Sdelphij * 3. All advertising materials mentioning features or use of this software
15285612Sdelphij *    must display the following acknowledgement:
16285612Sdelphij *	This product includes software developed by TooLs GmbH.
17285612Sdelphij * 4. The name of TooLs GmbH may not be used to endorse or promote products
18285612Sdelphij *    derived from this software without specific prior written permission.
19285612Sdelphij *
20285612Sdelphij * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21285612Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22285612Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23285612Sdelphij * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24285612Sdelphij * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25285612Sdelphij * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26285612Sdelphij * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27285612Sdelphij * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28285612Sdelphij * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29285612Sdelphij * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30285612Sdelphij *
31181834Sroberto *	$NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $
32285612Sdelphij */
33181834Sroberto/*
34181834Sroberto * Copyright (C) 2001 Benno Rice.
35181834Sroberto * All rights reserved.
36181834Sroberto *
37181834Sroberto * Redistribution and use in source and binary forms, with or without
38181834Sroberto * modification, are permitted provided that the following conditions
39285612Sdelphij * are met:
40181834Sroberto * 1. Redistributions of source code must retain the above copyright
41181834Sroberto *    notice, this list of conditions and the following disclaimer.
42285612Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
43181834Sroberto *    notice, this list of conditions and the following disclaimer in the
44181834Sroberto *    documentation and/or other materials provided with the distribution.
45285612Sdelphij *
46285612Sdelphij * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47285612Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48285612Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49285612Sdelphij * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50285612Sdelphij * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51181834Sroberto * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52181834Sroberto * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53181834Sroberto * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54285612Sdelphij * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55285612Sdelphij * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56181834Sroberto */
57285612Sdelphij
58285612Sdelphij#include <sys/cdefs.h>
59181834Sroberto__FBSDID("$FreeBSD: head/sys/powerpc/aim/clock.c 198428 2009-10-23 21:44:46Z nwhitehorn $");
60285612Sdelphij
61181834Sroberto#include <sys/param.h>
62285612Sdelphij#include <sys/systm.h>
63285612Sdelphij#include <sys/kernel.h>
64285612Sdelphij#include <sys/bus.h>
65181834Sroberto#include <sys/interrupt.h>
66285612Sdelphij#include <sys/pcpu.h>
67285612Sdelphij#include <sys/sysctl.h>
68285612Sdelphij#include <sys/timetc.h>
69285612Sdelphij
70285612Sdelphij#include <dev/ofw/openfirm.h>
71285612Sdelphij
72285612Sdelphij#include <machine/clock.h>
73285612Sdelphij#include <machine/cpu.h>
74285612Sdelphij#include <machine/intr.h>
75285612Sdelphij#include <machine/md_var.h>
76285612Sdelphij#include <machine/smp.h>
77285612Sdelphij
78285612Sdelphij/*
79285612Sdelphij * Initially we assume a processor with a bus frequency of 12.5 MHz.
80285612Sdelphij */
81285612Sdelphiju_long			ns_per_tick = 80;
82285612Sdelphijstatic u_long		ticks_per_sec = 12500000;
83285612Sdelphijstatic long		ticks_per_intr;
84285612Sdelphij
85285612Sdelphijstatic timecounter_get_t	decr_get_timecount;
86285612Sdelphij
87285612Sdelphijstatic struct timecounter	decr_timecounter = {
88285612Sdelphij	decr_get_timecount,	/* get_timecount */
89285612Sdelphij	0,			/* no poll_pps */
90285612Sdelphij	~0u,			/* counter_mask */
91285612Sdelphij	0,			/* frequency */
92285612Sdelphij	"decrementer"		/* name */
93285612Sdelphij};
94285612Sdelphij
95285612Sdelphijvoid
96285612Sdelphijdecr_intr(struct trapframe *frame)
97285612Sdelphij{
98285612Sdelphij	int32_t		tick, nticks;
99285612Sdelphij
100285612Sdelphij	/*
101285612Sdelphij	 * Check whether we are initialized.
102285612Sdelphij	 */
103285612Sdelphij	if (!ticks_per_intr)
104285612Sdelphij		return;
105285612Sdelphij
106285612Sdelphij	/*
107285612Sdelphij	 * Based on the actual time delay since the last decrementer reload,
108285612Sdelphij	 * we arrange for earlier interrupt next time.
109285612Sdelphij	 */
110285612Sdelphij	__asm ("mfdec %0" : "=r"(tick));
111285612Sdelphij	for (nticks = 0; tick < 0; nticks++)
112285612Sdelphij		tick += ticks_per_intr;
113285612Sdelphij	mtdec(tick);
114285612Sdelphij
115285612Sdelphij	while (nticks-- > 0) {
116285612Sdelphij		if (PCPU_GET(cpuid) == 0)
117285612Sdelphij			hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
118285612Sdelphij		else
119285612Sdelphij			hardclock_cpu(TRAPF_USERMODE(frame));
120285612Sdelphij
121285612Sdelphij		statclock(TRAPF_USERMODE(frame));
122285612Sdelphij		if (profprocs != 0)
123285612Sdelphij			profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
124285612Sdelphij	}
125285612Sdelphij}
126285612Sdelphij
127285612Sdelphijvoid
128285612Sdelphijdecr_init(void)
129285612Sdelphij{
130285612Sdelphij	struct cpuref cpu;
131285612Sdelphij	register_t msr;
132285612Sdelphij
133285612Sdelphij	/*
134285612Sdelphij	 * Check the BSP's timebase frequency. Sometimes we can't find the BSP, so fall
135285612Sdelphij	 * back to the first CPU in this case.
136285612Sdelphij	 */
137285612Sdelphij
138285612Sdelphij	if (platform_smp_get_bsp(&cpu) != 0)
139285612Sdelphij		platform_smp_first_cpu(&cpu);
140285612Sdelphij
141285612Sdelphij	ticks_per_sec = platform_timebase_freq(&cpu);
142285612Sdelphij
143285612Sdelphij	msr = mfmsr();
144285612Sdelphij	mtmsr(msr & ~PSL_EE);
145285612Sdelphij
146285612Sdelphij	ns_per_tick = 1000000000 / ticks_per_sec;
147285612Sdelphij	ticks_per_intr = ticks_per_sec / hz;
148285612Sdelphij	mtdec(ticks_per_intr);
149285612Sdelphij
150285612Sdelphij	set_cputicker(mftb, ticks_per_sec, 0);
151285612Sdelphij
152285612Sdelphij	mtmsr(msr);
153285612Sdelphij}
154285612Sdelphij
155285612Sdelphij#ifdef SMP
156285612Sdelphijvoid
157285612Sdelphijdecr_ap_init(void)
158285612Sdelphij{
159285612Sdelphij
160285612Sdelphij}
161285612Sdelphij#endif
162285612Sdelphij
163285612Sdelphijvoid
164285612Sdelphijdecr_tc_init(void)
165285612Sdelphij{
166285612Sdelphij	decr_timecounter.tc_frequency = ticks_per_sec;
167285612Sdelphij	tc_init(&decr_timecounter);
168285612Sdelphij}
169285612Sdelphij
170285612Sdelphijstatic unsigned
171285612Sdelphijdecr_get_timecount(struct timecounter *tc)
172285612Sdelphij{
173285612Sdelphij	register_t tb;
174181834Sroberto
175181834Sroberto	__asm __volatile("mftb %0" : "=r"(tb));
176181834Sroberto	return (tb);
177181834Sroberto}
178181834Sroberto
179181834Sroberto/*
180285612Sdelphij * Wait for about n microseconds (at least!).
181285612Sdelphij */
182285612Sdelphijvoid
183285612SdelphijDELAY(int n)
184285612Sdelphij{
185285612Sdelphij	u_quad_t	tb, ttb;
186285612Sdelphij
187285612Sdelphij	tb = mftb();
188285612Sdelphij	ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick;
189285612Sdelphij	while (tb < ttb)
190285612Sdelphij		tb = mftb();
191285612Sdelphij}
192285612Sdelphij
193285612Sdelphij/*
194285612Sdelphij * Nothing to do.
195285612Sdelphij */
196285612Sdelphijvoid
197285612Sdelphijcpu_startprofclock(void)
198285612Sdelphij{
199285612Sdelphij
200285612Sdelphij	/* Do nothing */
201285612Sdelphij}
202285612Sdelphij
203285612Sdelphijvoid
204285612Sdelphijcpu_stopprofclock(void)
205285612Sdelphij{
206285612Sdelphij}
207285612Sdelphij