clock.c revision 77957
177957Sbenno/*
277957Sbenno * Copyright (C) 1995, 1996 Wolfgang Solfrank.
377957Sbenno * Copyright (C) 1995, 1996 TooLs GmbH.
477957Sbenno * All rights reserved.
577957Sbenno *
677957Sbenno * Redistribution and use in source and binary forms, with or without
777957Sbenno * modification, are permitted provided that the following conditions
877957Sbenno * are met:
977957Sbenno * 1. Redistributions of source code must retain the above copyright
1077957Sbenno *    notice, this list of conditions and the following disclaimer.
1177957Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1277957Sbenno *    notice, this list of conditions and the following disclaimer in the
1377957Sbenno *    documentation and/or other materials provided with the distribution.
1477957Sbenno * 3. All advertising materials mentioning features or use of this software
1577957Sbenno *    must display the following acknowledgement:
1677957Sbenno *	This product includes software developed by TooLs GmbH.
1777957Sbenno * 4. The name of TooLs GmbH may not be used to endorse or promote products
1877957Sbenno *    derived from this software without specific prior written permission.
1977957Sbenno *
2077957Sbenno * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2177957Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2277957Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2377957Sbenno * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2477957Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2577957Sbenno * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2677957Sbenno * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2777957Sbenno * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2877957Sbenno * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2977957Sbenno * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3077957Sbenno *
3177957Sbenno *	$NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $	*/
3277957Sbenno */
3377957Sbenno
3477957Sbenno#ifndef lint
3577957Sbennostatic const char rcsid[] =
3677957Sbenno  "$FreeBSD: head/sys/powerpc/aim/clock.c 77957 2001-06-10 02:39:37Z benno $";
3777957Sbenno#endif /* not lint */
3877957Sbenno
3977957Sbenno#include <sys/param.h>
4077957Sbenno#include <sys/systm.h>
4177957Sbenno#include <sys/bus.h>
4277957Sbenno#include <sys/kernel.h>
4377957Sbenno#include <sys/timetc.h>
4477957Sbenno#include <sys/interrupt.h>
4577957Sbenno
4677957Sbenno#include <vm/vm.h>
4777957Sbenno
4877957Sbenno#include <dev/ofw/openfirm.h>
4977957Sbenno
5077957Sbenno#include <machine/clock.h>
5177957Sbenno#include <machine/cpu.h>
5277957Sbenno
5377957Sbenno#if 0 /* XXX */
5477957Sbenno#include "adb.h"
5577957Sbenno#else
5677957Sbenno#define	NADB	0
5777957Sbenno#endif
5877957Sbenno
5977957Sbenno/*
6077957Sbenno * Initially we assume a processor with a bus frequency of 12.5 MHz.
6177957Sbenno */
6277957Sbennostatic u_long		ns_per_tick = 80;
6377957Sbennostatic long		ticks_per_intr;
6477957Sbennostatic volatile u_long	lasttb;
6577957Sbenno
6677957Sbenno#define	SECDAY		86400
6777957Sbenno#define	DIFF19041970	2082844800
6877957Sbenno
6977957Sbenno#if NADB > 0
7077957Sbennoextern int adb_read_date_time __P((int *));
7177957Sbennoextern int adb_set_date_time __P((int));
7277957Sbenno#endif
7377957Sbenno
7477957Sbennostatic int		clockinitted = 0;
7577957Sbenno
7677957Sbennovoid
7777957Sbennoinittodr(time_t base)
7877957Sbenno{
7977957Sbenno	time_t		deltat;
8077957Sbenno	u_int		rtc_time;
8177957Sbenno	struct timespec	ts;
8277957Sbenno
8377957Sbenno	/*
8477957Sbenno	 * If we can't read from RTC, use the fs time.
8577957Sbenno	 */
8677957Sbenno#if NADB > 0
8777957Sbenno	if (adb_read_date_time(&rtc_time) < 0)
8877957Sbenno#endif
8977957Sbenno	{
9077957Sbenno		ts.tv_sec = base;
9177957Sbenno		ts.tv_nsec = 0;
9277957Sbenno		tc_setclock(&ts);
9377957Sbenno		return;
9477957Sbenno	}
9577957Sbenno	clockinitted = 1;
9677957Sbenno	ts.tv_sec = rtc_time - DIFF19041970;
9777957Sbenno
9877957Sbenno	deltat = ts.tv_sec - base;
9977957Sbenno	if (deltat < 0) {
10077957Sbenno		deltat = -deltat;
10177957Sbenno	}
10277957Sbenno	if (deltat < 2 * SECDAY) {
10377957Sbenno		tc_setclock(&ts);
10477957Sbenno		return;
10577957Sbenno	}
10677957Sbenno
10777957Sbenno	printf("WARNING: clock %s %d days",
10877957Sbenno	    ts.tv_sec < base ? "lost" : "gained", (int)(deltat / SECDAY));
10977957Sbenno
11077957Sbenno	printf(" -- CHECK AND RESET THE DATE!\n");
11177957Sbenno}
11277957Sbenno
11377957Sbenno/*
11477957Sbenno * Similar to the above
11577957Sbenno */
11677957Sbennovoid
11777957Sbennoresettodr()
11877957Sbenno{
11977957Sbenno#if NADB > 0
12077957Sbenno	u_int	rtc_time;
12177957Sbenno
12277957Sbenno	if (clockinitted) {
12377957Sbenno		rtc_time = time.tv_sec + DIFF19041970;
12477957Sbenno		adb_set_date_time(rtc_time);
12577957Sbenno	}
12677957Sbenno#endif
12777957Sbenno}
12877957Sbenno
12977957Sbennovoid
13077957Sbennodecr_intr(struct clockframe *frame)
13177957Sbenno{
13277957Sbenno	u_long	tb;
13377957Sbenno	long	tick;
13477957Sbenno	int	nticks;
13577957Sbenno
13677957Sbenno	/*
13777957Sbenno	 * Check whether we are initialized.
13877957Sbenno	 */
13977957Sbenno	if (!ticks_per_intr)
14077957Sbenno		return;
14177957Sbenno
14277957Sbenno	/*
14377957Sbenno	 * Based on the actual time delay since the last decrementer reload,
14477957Sbenno	 * we arrange for earlier interrupt next time.
14577957Sbenno	 */
14677957Sbenno	__asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick));
14777957Sbenno	for (nticks = 0; tick < 0; nticks++)
14877957Sbenno		tick += ticks_per_intr;
14977957Sbenno	__asm __volatile ("mtdec %0" :: "r"(tick));
15077957Sbenno	/*
15177957Sbenno	 * lasttb is used during microtime. Set it to the virtual
15277957Sbenno	 * start of this tick interval.
15377957Sbenno	 */
15477957Sbenno	lasttb = tb + tick - ticks_per_intr;
15577957Sbenno
15677957Sbenno#if 0 /* XXX */
15777957Sbenno	intrcnt[CNT_CLOCK]++;
15877957Sbenno	{
15977957Sbenno		int pri;
16077957Sbenno		int msr;
16177957Sbenno
16277957Sbenno		pri = splclock();
16377957Sbenno		if (pri & (1 << SPL_CLOCK)) {
16477957Sbenno			tickspending += nticks;
16577957Sbenno		}
16677957Sbenno		else {
16777957Sbenno			nticks += tickspending;
16877957Sbenno			tickspending = 0;
16977957Sbenno
17077957Sbenno			/*
17177957Sbenno			 * Reenable interrupts
17277957Sbenno			 */
17377957Sbenno			__asm __volatile ("mfmsr %0; ori %0, %0, %1; mtmsr %0"
17477957Sbenno				          : "=r"(msr) : "K"(PSL_EE));
17577957Sbenno
17677957Sbenno			/*
17777957Sbenno			 * Do standard timer interrupt stuff.
17877957Sbenno			 * Do softclock stuff only on the last iteration.
17977957Sbenno			 */
18077957Sbenno			frame->pri = pri | (1 << SIR_CLOCK);
18177957Sbenno			while (--nticks > 0)
18277957Sbenno				hardclock(frame);
18377957Sbenno			frame->pri = pri;
18477957Sbenno			hardclock(frame);
18577957Sbenno		}
18677957Sbenno		splx(pri);
18777957Sbenno	}
18877957Sbenno#endif
18977957Sbenno}
19077957Sbenno
19177957Sbennovoid
19277957Sbennocpu_initclocks(void)
19377957Sbenno{
19477957Sbenno
19577957Sbenno	/* Do nothing */
19677957Sbenno}
19777957Sbenno
19877957Sbennostatic __inline u_quad_t
19977957Sbennomftb(void)
20077957Sbenno{
20177957Sbenno	u_long		scratch;
20277957Sbenno	u_quad_t	tb;
20377957Sbenno
20477957Sbenno	__asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b"
20577957Sbenno	      : "=r"(tb), "=r"(scratch));
20677957Sbenno	return tb;
20777957Sbenno}
20877957Sbenno
20977957Sbenno/*
21077957Sbenno * Wait for about n microseconds (at least!).
21177957Sbenno */
21277957Sbennovoid
21377957Sbennodelay(unsigned n)
21477957Sbenno{
21577957Sbenno	u_quad_t	tb;
21677957Sbenno	u_long		tbh, tbl, scratch;
21777957Sbenno
21877957Sbenno	tb = mftb();
21977957Sbenno	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
22077957Sbenno	tbh = tb >> 32;
22177957Sbenno	tbl = tb;
22277957Sbenno	__asm ("1: mftbu %0; cmplw %0,%1; blt 1b; bgt 2f;"
22377957Sbenno	       "mftb %0; cmplw %0,%2; blt 1b; 2:"
22477957Sbenno	       :: "r"(scratch), "r"(tbh), "r"(tbl));
22577957Sbenno}
22677957Sbenno
22777957Sbenno/*
22877957Sbenno * Nothing to do.
22977957Sbenno */
23077957Sbennovoid
23177957Sbennosetstatclockrate(int arg)
23277957Sbenno{
23377957Sbenno
23477957Sbenno	/* Do nothing */
23577957Sbenno}
236