patch-2.1.79 linux/arch/ppc/kernel/time.c
Next file: linux/arch/ppc/kernel/time.h
Previous file: linux/arch/ppc/kernel/syscalls.c
Back to the patch index
Back to the overall index
- Lines: 211
- Date:
Mon Jan 12 15:18:13 1998
- Orig file:
v2.1.78/linux/arch/ppc/kernel/time.c
- Orig date:
Thu Sep 4 17:07:29 1997
diff -u --recursive --new-file v2.1.78/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
@@ -1,5 +1,5 @@
/*
- * $Id: time.c,v 1.10 1997/08/27 22:06:56 cort Exp $
+ * $Id: time.c,v 1.17 1997/12/28 22:47:21 paulus Exp $
* Common time routines among all ppc machines.
*
* Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -41,22 +41,6 @@
unsigned count_period_num; /* 1 decrementer count equals */
unsigned count_period_den; /* count_period_num / count_period_den us */
-/* Accessor functions for the decrementer register. */
-inline unsigned long
-get_dec(void)
-{
- int ret;
-
- asm volatile("mfspr %0,22" : "=r" (ret) :);
- return ret;
-}
-
-inline void
-set_dec(int val)
-{
- asm volatile("mtspr 22,%0" : : "r" (val));
-}
-
/*
* timer_interrupt - gets called when the decrementer overflows,
* with interrupts disabled.
@@ -125,22 +109,6 @@
void
time_init(void)
{
- /* pmac hasn't yet called via_cuda_init() */
- if ( _machine != _MACH_Pmac )
- {
-
- if ( _machine == _MACH_chrp )
- xtime.tv_sec = chrp_get_rtc_time();
- else /* assume prep */
- xtime.tv_sec = prep_get_rtc_time();
- xtime.tv_usec = 0;
- /*
- * mark the rtc/on-chip timer as in sync
- * so we don't update right away
- */
- last_rtc_update = xtime.tv_sec;
- }
-
if ((_get_PVR() >> 16) == 1) {
/* 601 processor: dec counts down by 128 every 128ns */
decrementer_count = DECREMENTER_COUNT_601;
@@ -148,22 +116,35 @@
count_period_den = COUNT_PERIOD_DEN_601;
}
- switch (_machine)
- {
+ switch (_machine) {
case _MACH_Pmac:
- pmac_calibrate_decr();
+ /* can't call pmac_get_rtc_time() yet,
+ because via-cuda isn't initialized yet. */
+ if ((_get_PVR() >> 16) != 1)
+ pmac_calibrate_decr();
set_rtc_time = pmac_set_rtc_time;
break;
- case _MACH_IBM:
- case _MACH_Motorola:
- prep_calibrate_decr();
- set_rtc_time = prep_set_rtc_time;
- break;
case _MACH_chrp:
- chrp_calibrate_decr();
+ chrp_time_init();
+ xtime.tv_sec = chrp_get_rtc_time();
+ if ((_get_PVR() >> 16) != 1)
+ chrp_calibrate_decr();
set_rtc_time = chrp_set_rtc_time;
break;
+ case _MACH_prep:
+ xtime.tv_sec = prep_get_rtc_time();
+ prep_calibrate_decr();
+ set_rtc_time = prep_set_rtc_time;
+ break;
}
+ xtime.tv_usec = 0;
+
+ /*
+ * mark the rtc/on-chip timer as in sync
+ * so we don't update right away
+ */
+ last_rtc_update = xtime.tv_sec;
+
set_dec(decrementer_count);
}
@@ -180,7 +161,7 @@
unsigned long flags;
save_flags(flags);
-
+
#define TIMER0_COUNT 0x40
#define TIMER_CONTROL 0x43
/* set timer to periodic mode */
@@ -199,7 +180,7 @@
void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs)
{
- int freq, divisor;
+ unsigned long freq, divisor;
static unsigned long t1 = 0, t2 = 0;
if ( !t1 )
@@ -209,9 +190,14 @@
t2 = get_dec();
t2 = t1-t2; /* decr's in 1/HZ */
t2 = t2*HZ; /* # decrs in 1s - thus in Hz */
+if ( (t2>>20) > 100 )
+{
+ printk("Decrementer frequency too high: %luMHz. Using 15MHz.\n",t2>>20);
+ t2 = 998700000/60;
+}
freq = t2 * 60; /* try to make freq/1e6 an integer */
divisor = 60;
- printk("time_init: decrementer frequency = %d/%d (%luMHz)\n",
+ printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
freq, divisor,t2>>20);
decrementer_count = freq / HZ / divisor;
count_period_num = divisor;
@@ -220,19 +206,6 @@
}
}
-void chrp_calibrate_decr(void)
-{
- int freq, fp, divisor;
-
- fp = 16666000; /* hardcoded for now */
- freq = fp*60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
-}
-
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
@@ -249,9 +222,9 @@
* machines were long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
-inline unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
+unsigned long mktime(unsigned int year, unsigned int mon,
+ unsigned int day, unsigned int hour,
+ unsigned int min, unsigned int sec)
{
if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
@@ -266,3 +239,45 @@
)*60 + sec; /* finally seconds */
}
+#define TICK_SIZE tick
+#define FEBRUARY 2
+#define STARTOFTIME 1970
+#define SECDAY 86400L
+#define SECYR (SECDAY * 365)
+#define leapyear(year) ((year) % 4 == 0)
+#define days_in_year(a) (leapyear(a) ? 366 : 365)
+#define days_in_month(a) (month_days[(a) - 1])
+
+static int month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+void to_tm(int tim, struct rtc_time * tm)
+{
+ register int i;
+ register long hms, day;
+
+ day = tim / SECDAY;
+ hms = tim % SECDAY;
+
+ /* Hours, minutes, seconds are easy */
+ tm->tm_hour = hms / 3600;
+ tm->tm_min = (hms % 3600) / 60;
+ tm->tm_sec = (hms % 3600) % 60;
+
+ /* Number of years in days */
+ for (i = STARTOFTIME; day >= days_in_year(i); i++)
+ day -= days_in_year(i);
+ tm->tm_year = i;
+
+ /* Number of months in days left */
+ if (leapyear(tm->tm_year))
+ days_in_month(FEBRUARY) = 29;
+ for (i = 1; day >= days_in_month(i); i++)
+ day -= days_in_month(i);
+ days_in_month(FEBRUARY) = 28;
+ tm->tm_mon = i;
+
+ /* Days are what is left over (+1) from all that. */
+ tm->tm_mday = day + 1;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov