patch-2.1.79 linux/arch/ppc/kernel/pmac_time.c
Next file: linux/arch/ppc/kernel/ppc_asm.tmpl
Previous file: linux/arch/ppc/kernel/pmac_support.c
Back to the patch index
Back to the overall index
- Lines: 122
- Date:
Mon Jan 12 15:18:13 1998
- Orig file:
v2.1.78/linux/arch/ppc/kernel/pmac_time.c
- Orig date:
Mon Aug 18 18:19:44 1997
diff -u --recursive --new-file v2.1.78/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
@@ -2,9 +2,7 @@
* Support for periodic interrupts (100 per second) and for getting
* the current time from the RTC on Power Macintoshes.
*
- * At present, we use the decrementer register in the 601 CPU
- * for our periodic interrupts. This will probably have to be
- * changed for other processors.
+ * We use the decrementer register for our periodic interrupts.
*
* Paul Mackerras August 1996.
* Copyright (C) 1996 Paul Mackerras.
@@ -15,17 +13,79 @@
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
+#include <asm/adb.h>
#include <asm/cuda.h>
#include <asm/prom.h>
#include <asm/system.h>
#include "time.h"
-
/* Apparently the RTC stores seconds since 1 Jan 1904 */
#define RTC_OFFSET 2082844800
/*
+ * Calibrate the decrementer frequency with the VIA timer 1.
+ */
+#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
+
+/* VIA registers */
+#define RS 0x200 /* skip between registers */
+#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
+#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
+#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
+#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
+#define ACR (11*RS) /* Auxiliary control register */
+#define IFR (13*RS) /* Interrupt flag register */
+
+/* Bits in ACR */
+#define T1MODE 0xc0 /* Timer 1 mode */
+#define T1MODE_CONT 0x40 /* continuous interrupts */
+
+/* Bits in IFR and IER */
+#define T1_INT 0x40 /* Timer 1 interrupt */
+
+static int via_calibrate_decr(void)
+{
+ struct device_node *vias;
+ volatile unsigned char *via;
+ int count = VIA_TIMER_FREQ_6 / HZ;
+ unsigned int dstart, dend;
+
+ vias = find_devices("via-cuda");
+ if (vias == 0)
+ vias = find_devices("via-pmu");
+ if (vias == 0 || vias->n_addrs == 0)
+ return 0;
+ via = (volatile unsigned char *) vias->addrs[0].address;
+
+ /* set timer 1 for continuous interrupts */
+ out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
+ /* set the counter to a small value */
+ out_8(&via[T1CH], 2);
+ /* set the latch to `count' */
+ out_8(&via[T1LL], count);
+ out_8(&via[T1LH], count >> 8);
+ /* wait until it hits 0 */
+ while ((in_8(&via[IFR]) & T1_INT) == 0)
+ ;
+ dstart = get_dec();
+ /* clear the interrupt & wait until it hits 0 again */
+ in_8(&via[T1CL]);
+ while ((in_8(&via[IFR]) & T1_INT) == 0)
+ ;
+ dend = get_dec();
+
+ decrementer_count = (dstart - dend) / 6;
+ count_period_num = 60;
+ count_period_den = decrementer_count * 6 * HZ / 100000;
+
+ printk(KERN_INFO "via_calibrate_decr: decrementer_count = %u (%u ticks)\n",
+ decrementer_count, dstart - dend);
+
+ return 1;
+}
+
+/*
* Query the OF and get the decr frequency.
* This was taken from the pmac time_init() when merging the prep/pmac
* time functions.
@@ -35,6 +95,9 @@
struct device_node *cpu;
int freq, *fp, divisor;
+ if (via_calibrate_decr())
+ return;
+
/*
* The cpu node should have a timebase-frequency property
* to tell us the rate at which the decrementer counts.
@@ -57,11 +120,11 @@
unsigned long
pmac_get_rtc_time(void)
{
- struct cuda_request req;
+ struct adb_request req;
/* Get the time from the RTC */
cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME);
- while (!req.got_reply)
+ while (!req.complete)
cuda_poll();
if (req.reply_len != 7)
printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
@@ -84,4 +147,5 @@
{
xtime.tv_sec = pmac_get_rtc_time();
xtime.tv_usec = 0;
+ last_rtc_update = xtime.tv_sec;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov