Skip to contentSkip to conversation

alpha - generic_init_pit - why using RTC for calibration?

DISCUSSION Oleg I. Vdovikin 4 participants 12 messages Jun 29, 2001 – Jul 6, 2001 Alpha port

lore
Share & tools
lore
#0 lore raw

Hello,

    we've a bunch of UP2000/UP2000+ boards (similar to DP264) with 666MHz

EV67 Alphas (we're building large Alpha cluster). And we're regulary see "HWRPB cycle frequency bogus" and the measured value for the speed in the range of 519 MHz - 666 MHz. And this value changes in this range from boot to boot. So why this happens???

Initialy we've an idea this boards has frequency stability problem. But
then I've decided to add simple recalculation for est_cycle_freq on every 1024 ticks which happens on boot processor (I've used rpcc for the counting). I've added 10 lines to the timer_interrupt function. And I was really wondered: the clock are rock solid - near 666 MHz and +- 1Khz stability (I'm thinking it's some non constant overhead in the irq handlers).

So, I've looked deeper. And here is the question: why using RTC for
calibration and UIP bit? This bit guarantees nothing - the specs said when it's raised to 1 if clock update occures in the ~244 ms! But it does not said this happens regulary in the same time for this 244 ms!

So, the final question: why we're not using the aproach which is used by
x86 time.c? I.e. why not to use CTC channel 2 for calibration?

Please correct me, if there is something wrong.

Thanks,
Oleg.

#1 lore raw
Quoted 5 lines · Oleg I. Vdovikin
    we've a bunch of UP2000/UP2000+ boards (similar to DP264) with 666MHz

EV67 Alphas (we're building large Alpha cluster). And we're regulary see "HWRPB cycle frequency bogus" and the measured value for the speed in the range of 519 MHz - 666 MHz. And this value changes in this range from boot to boot. So why this happens???

This is known problem with Cypress cy82c693 SIO. The RTC on this chip sometimes need a very long time (up to several minutes) to settle down after reset/power-up. But I thought it's fixed on newer systems with "ub" revision of the chip... :-(

Quoted 2 lines

So, the final question: why we're not using the aproach which is used by
x86 time.c? I.e. why not to use CTC channel 2 for calibration?

Good idea. The patch below works reliably on my sx164.

Ivan.

arch/alpha/kernel/time.c +60 -0
@@ -169,6 +169,63 @@ common_init_rtc(void)
 	init_rtc_irq();
 }
 
+/*
+ * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
+ * arch/i386/time.c.
+ */
+
+#define CALIBRATE_LATCH	(52 * LATCH)
+#define CALIBRATE_TIME	(52 * 1000020 / HZ)
+
+static unsigned long __init
+calibrate_cc(void)
+{
+	int cc;
+	unsigned long count = 0;
+
+       /* Set the Gate high, disable speaker */
+	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+	/*
+	 * Now let's take care of CTC channel 2
+	 *
+	 * Set the Gate high, program CTC channel 2 for mode 0,
+	 * (interrupt on terminal count mode), binary count,
+	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+	 */
+	outb(0xb0, 0x43);			/* binary, mode 0, LSB/MSB, Ch 2 */
+	outb(CALIBRATE_LATCH & 0xff, 0x42);	/* LSB of count */
+	outb(CALIBRATE_LATCH >> 8, 0x42);	/* MSB of count */
+
+	cc = rpcc();
+	do {
+		count++;
+	} while ((inb(0x61) & 0x20) == 0);
+	cc = rpcc() - cc;
+
+	/* Error: ECTCNEVERSET */
+	if (count <= 1)
+		goto bad_ctc;
+
+	/* Error: ECPUTOOFAST */
+	if (count >> 32)
+		goto bad_ctc;
+
+	/* Error: ECPUTOOSLOW */
+	if (cc <= CALIBRATE_TIME)
+		goto bad_ctc;
+
+	return ((long)cc * 1000000) / CALIBRATE_TIME;
+
+	/*
+	 * The CTC wasn't reliable: we got a hit on the very first read,
+	 * or the CPU was so fast/slow that the quotient wouldn't fit in
+	 * 32 bits..
+	 */
+bad_ctc:
+	return 0;
+}
+
 void __init
 time_init(void)
 {
@@ -176,6 +233,9 @@ time_init(void)
 	unsigned long cycle_freq, one_percent;
 	long diff;
 
+	/* Calibrate CPU clock -- attempt #1. If this fails, use RTC. */
+	if (!est_cycle_freq)
+		est_cycle_freq = calibrate_cc();
 	/*
 	 * The Linux interpretation of the CMOS clock register contents:
 	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
#2 lore raw
In reply to Oleg I. Vdovikin

Ivan, thanks. I will minorly adjust the patch, prepare it for 2.2.x series and then post it.

Thanks,
Oleg.

P.S. Richard, any thoughts?

----- Original Message -----
From: "Ivan Kokshaysky" <[email protected]>
To: "Oleg I. Vdovikin" <[email protected]>
Cc: "Richard Henderson" <[email protected]>; <[email protected]>
Sent: Friday, June 29, 2001 9:19 PM
Subject: Re: alpha - generic_init_pit - why using RTC for calibration?

Quoted 2 lines · Oleg I. Vdovikin
Quoted 1 line
    we've a bunch of UP2000/UP2000+ boards (similar to DP264) with

666MHz

Quoted 2 lines
Quoted 2 lines

EV67 Alphas (we're building large Alpha cluster). And we're regulary see "HWRPB cycle frequency bogus" and the measured value for the speed in

the

Quoted 1 line
Quoted 1 line

range of 519 MHz - 666 MHz. And this value changes in this range from

boot

Quoted 8 lines
Quoted 1 line

to boot. So why this happens???

This is known problem with Cypress cy82c693 SIO. The RTC on this chip sometimes need a very long time (up to several minutes) to settle down after reset/power-up. But I thought it's fixed on newer systems with "ub" revision of the chip... :-(

Quoted 1 line

So, the final question: why we're not using the aproach which is

used by

Quoted 83 lines
Quoted 1 line

x86 time.c? I.e. why not to use CTC channel 2 for calibration?

Good idea. The patch below works reliably on my sx164.

Ivan.

arch/alpha/kernel/time.c Fri Jun 29 20:58:09 2001 renamed from arch/alpha/kernel/time.c Mon Nov 13 06:27:11 2000 +60 -0
@@ -169,6 +169,63 @@ common_init_rtc(void)
  init_rtc_irq();
 }
 
+/*
+ * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
+ * arch/i386/time.c.
+ */
+
+#define CALIBRATE_LATCH (52 * LATCH)
+#define CALIBRATE_TIME (52 * 1000020 / HZ)
+
+static unsigned long __init
+calibrate_cc(void)
+{
+ int cc;
+ unsigned long count = 0;
+
+       /* Set the Gate high, disable speaker */
+ outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+ /*
+ * Now let's take care of CTC channel 2
+ *
+ * Set the Gate high, program CTC channel 2 for mode 0,
+ * (interrupt on terminal count mode), binary count,
+ * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+ */
+ outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
+ outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
+
+ cc = rpcc();
+ do {
+ count++;
+ } while ((inb(0x61) & 0x20) == 0);
+ cc = rpcc() - cc;
+
+ /* Error: ECTCNEVERSET */
+ if (count <= 1)
+ goto bad_ctc;
+
+ /* Error: ECPUTOOFAST */
+ if (count >> 32)
+ goto bad_ctc;
+
+ /* Error: ECPUTOOSLOW */
+ if (cc <= CALIBRATE_TIME)
+ goto bad_ctc;
+
+ return ((long)cc * 1000000) / CALIBRATE_TIME;
+
+ /*
+ * The CTC wasn't reliable: we got a hit on the very first read,
+ * or the CPU was so fast/slow that the quotient wouldn't fit in
+ * 32 bits..
+ */
+bad_ctc:
+ return 0;
+}
+
 void __init
 time_init(void)
 {
@@ -176,6 +233,9 @@ time_init(void)
  unsigned long cycle_freq, one_percent;
  long diff;
 
+ /* Calibrate CPU clock -- attempt #1. If this fails, use RTC. */
+ if (!est_cycle_freq)
+ est_cycle_freq = calibrate_cc();
  /*
  * The Linux interpretation of the CMOS clock register contents:
  * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
#3 lore raw
In reply to Oleg I. Vdovikin

Here is the patch against the buggy Cypress RTC which is found on some
Alpha boards. It's tested with 2.2.16 & 2.2.19 kernels and as seems should work with 2.4.x kernels. This patch differs from initial Ivan's version by the "cc" variable type & different calibrate divisor usage for better accuracy.

Please consider applying this patch against the 2.2.x tree. It's really
needed due to overall performance reasons.

Thanks,
Oleg.

arch/alpha/kernel/time.c Mon Jul 2 15:47:45 2001 renamed from arch/alpha/kernel/time.c.orig Mon Jul 2 14:05:09 2001 +47 -0
@@ -231,6 +231,49 @@
  outb(0x13, 0x42);
 }
 
+/*
+ * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
+ * arch/i386/time.c.
+ */
+
+#define CALIBRATE_DIVISOR 0xffff
+
+static unsigned long __init
+calibrate_cc(void)
+{
+ unsigned int cc;
+ unsigned long count = 0;
+
+ /* Set the Gate high, disable speaker */
+ outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+ /*
+  * Now let's take care of CTC channel 2
+  *
+  * Set the Gate high, program CTC channel 2 for mode 0,
+  * (interrupt on terminal count mode), binary count,
+  * load maximum divisor we can get for accuracy - 65535
+  */
+
+ outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(CALIBRATE_DIVISOR & 0xff, 0x42); /* LSB of count */
+ outb(CALIBRATE_DIVISOR >> 8, 0x42); /* MSB of count */
+
+ /* we still should not hang if timer not runing or N/A */
+ for (cc = rpcc(); (inb(0x61) & 0x20) == 0 && !(count >> 32); count++);
+
+ /* cycles delta */
+ cc = rpcc() - cc;
+
+ /* check for the reliable result */
+ if ((count < 1) || (count >> 32))
+     return 0;
+
+ /* and the final result in HZ */
+ return ((unsigned long)cc * CLOCK_TICK_RATE) / CALIBRATE_DIVISOR;
+}
+
+
 void
 time_init(void)
 {
@@ -239,6 +282,10 @@
  unsigned long cycle_freq, ppm_error;
  long diff;
 
+ /* Calibrate CPU clock using CTC. If this fails, use RTC. */
+ if (!est_cycle_freq)
+     est_cycle_freq = calibrate_cc();
+
  /*
   * The Linux interpretation of the CMOS clock register contents:
   * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
arch/alpha/kernel/time.c renamed from arch/alpha/kernel/time.c.orig +48 -1

67 lines not on this page · raw message

#4 lore raw
In reply to Oleg I. Vdovikin
Quoted 1 line · Ivan Kokshaysky

Good idea. The patch below works reliably on my sx164.

Reasonable. Here I've cleaned up time_init a tad as well.

r~

alpha/kernel/time.c renamed from alpha/kernel/time.c.orig +77 -15
@@ -169,6 +169,77 @@ common_init_rtc(void)
 	init_rtc_irq();
 }
 
+/*
+ * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
+ * arch/i386/time.c.
+ */
+
+#define CALIBRATE_LATCH	(52 * LATCH)
+#define CALIBRATE_TIME	(52 * 1000020 / HZ)
+
+static unsigned long __init
+calibrate_cc_with_pic(void)
+{
+	int cc;
+	unsigned long count = 0;
+
+	/* Set the Gate high, disable speaker */
+	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+	/*
+	 * Now let's take care of CTC channel 2
+	 *
+	 * Set the Gate high, program CTC channel 2 for mode 0,
+	 * (interrupt on terminal count mode), binary count,
+	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+	 */
+	outb(0xb0, 0x43);		/* binary, mode 0, LSB/MSB, Ch 2 */
+	outb(CALIBRATE_LATCH & 0xff, 0x42);	/* LSB of count */
+	outb(CALIBRATE_LATCH >> 8, 0x42);	/* MSB of count */
+
+	cc = rpcc();
+	do {
+		count++;
+	} while ((inb(0x61) & 0x20) == 0);
+	cc = rpcc() - cc;
+
+	/* Error: ECTCNEVERSET */
+	if (count <= 1)
+		goto bad_ctc;
+
+	/* Error: ECPUTOOFAST */
+	if (count >> 32)
+		goto bad_ctc;
+
+	/* Error: ECPUTOOSLOW */
+	if (cc <= CALIBRATE_TIME)
+		goto bad_ctc;
+
+	return ((long)cc * 1000000) / CALIBRATE_TIME;
+
+	/*
+	 * The CTC wasn't reliable: we got a hit on the very first read,
+	 * or the CPU was so fast/slow that the quotient wouldn't fit in
+	 * 32 bits..
+	 */
+ bad_ctc:
+	return 0;
+}
+
+/* The Linux interpretation of the CMOS clock register contents:
+   When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+   RTC registers show the second which has precisely just started.
+   Let's hope other operating systems interpret the RTC the same way.  */
+
+static unsigned long __init
+rpcc_after_update_in_progress(void)
+{
+	do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
+	do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+
+	return rpcc();
+}
+
 void __init
 time_init(void)
 {
@@ -176,24 +247,15 @@ time_init(void)
 	unsigned long cycle_freq, one_percent;
 	long diff;
 
-	/*
-	 * The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-	do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
-	do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+	/* Calibrate CPU clock -- attempt #1.  */
+	if (!est_cycle_freq)
+		est_cycle_freq = calibrate_cc_with_pic();
 
-	/* Read cycle counter exactly on falling edge of update flag */
-	cc1 = rpcc();
+	cc1 = rpcc_after_update_in_progress();
 
+	/* Calibrate CPU clock -- attempt #2.  */
 	if (!est_cycle_freq) {
-		/* Sometimes the hwrpb->cycle_freq value is bogus. 
-		   Go another round to check up on it and see.  */
-		do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
-		do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
-		cc2 = rpcc();
+		cc2 = rpcc_after_update_in_progress();
 		est_cycle_freq = cc2 - cc1;
 		cc1 = cc2;
 	}
#5 lore raw
In reply to Oleg I. Vdovikin

Richard, thanks. But please use calibrate_cc version which I've submited
as a patch - it gives more accuracy with maximum latch we can ever use and has cc's type changed to 'unsigned int' to prevent problems when rpcc overflows.

Oleg.

----- Original Message -----
From: "Richard Henderson" <[email protected]>
To: "Ivan Kokshaysky" <[email protected]>; <[email protected]>; <[email protected]>
Cc: "Oleg I. Vdovikin" <[email protected]>; <[email protected]>
Sent: Wednesday, July 04, 2001 10:45 PM
Subject: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?

Quoted 127 lines · Ivan Kokshaysky
Quoted 1 line

Good idea. The patch below works reliably on my sx164.

Reasonable. Here I've cleaned up time_init a tad as well.

r~

alpha/kernel/time.c Fri Jun 29 11:35:52 2001 renamed from alpha/kernel/time.c.orig Fri Jun 29 11:24:03 2001 +77 -16
@@ -169,6 +169,77 @@ common_init_rtc(void)
  init_rtc_irq();
 }
 
+/*
+ * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
+ * arch/i386/time.c.
+ */
+
+#define CALIBRATE_LATCH (52 * LATCH)
+#define CALIBRATE_TIME (52 * 1000020 / HZ)
+
+static unsigned long __init
+calibrate_cc_with_pic(void)
+{
+ int cc;
+ unsigned long count = 0;
+
+ /* Set the Gate high, disable speaker */
+ outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+ /*
+ * Now let's take care of CTC channel 2
+ *
+ * Set the Gate high, program CTC channel 2 for mode 0,
+ * (interrupt on terminal count mode), binary count,
+ * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+ */
+ outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
+ outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
+
+ cc = rpcc();
+ do {
+ count++;
+ } while ((inb(0x61) & 0x20) == 0);
+ cc = rpcc() - cc;
+
+ /* Error: ECTCNEVERSET */
+ if (count <= 1)
+ goto bad_ctc;
+
+ /* Error: ECPUTOOFAST */
+ if (count >> 32)
+ goto bad_ctc;
+
+ /* Error: ECPUTOOSLOW */
+ if (cc <= CALIBRATE_TIME)
+ goto bad_ctc;
+
+ return ((long)cc * 1000000) / CALIBRATE_TIME;
+
+ /*
+ * The CTC wasn't reliable: we got a hit on the very first read,
+ * or the CPU was so fast/slow that the quotient wouldn't fit in
+ * 32 bits..
+ */
+ bad_ctc:
+ return 0;
+}
+
+/* The Linux interpretation of the CMOS clock register contents:
+   When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+   RTC registers show the second which has precisely just started.
+   Let's hope other operating systems interpret the RTC the same way.  */
+
+static unsigned long __init
+rpcc_after_update_in_progress(void)
+{
+ do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
+ do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+
+ return rpcc();
+}
+
 void __init
 time_init(void)
 {
@@ -176,24 +247,15 @@ time_init(void)
  unsigned long cycle_freq, one_percent;
  long diff;
 
- /*
- * The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
- do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+ /* Calibrate CPU clock -- attempt #1.  */
+ if (!est_cycle_freq)
+ est_cycle_freq = calibrate_cc_with_pic();
 
- /* Read cycle counter exactly on falling edge of update flag */
- cc1 = rpcc();
+ cc1 = rpcc_after_update_in_progress();
 
+ /* Calibrate CPU clock -- attempt #2.  */
  if (!est_cycle_freq) {
- /* Sometimes the hwrpb->cycle_freq value is bogus.
-    Go another round to check up on it and see.  */
- do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
- do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
- cc2 = rpcc();
+ cc2 = rpcc_after_update_in_progress();
  est_cycle_freq = cc2 - cc1;
  cc1 = cc2;
  }
-

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#6 lore raw
In reply to Oleg I. Vdovikin

That's it.

Please also include my old rtc patch for 2.2.x series into official 2.2.20 kernel.

Thanks,
Oleg.

-------------
From: "Jeff Garzik" <[email protected]>
Subject: Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?

Quoted 10 lines

Oleg,

The official kernel now carries Richard's version. Can you post a diff on linux-kernel against version 2.4.7-pre2 perhaps, which cleans up Richard's code to yours?
--

Jeff Garzik      | Thalidomide, eh?
Building 1024    | So you're saying the eggplant has an accomplice?
MandrakeSoft     |
arch/alpha/kernel/time.c renamed from arch/alpha/kernel/time.c.orig +48 -1
@@ -231,6 +231,49 @@
 	outb(0x13, 0x42);
 }
 
+/*
+ * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
+ * arch/i386/time.c.
+ */
+
+#define CALIBRATE_DIVISOR	0xffff
+
+static unsigned long __init
+calibrate_cc(void)
+{
+	unsigned int cc;
+	unsigned long count = 0;
+	
+	/* Set the Gate high, disable speaker */
+	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+	
+	/*
+	 * Now let's take care of CTC channel 2
+	 *
+	 * Set the Gate high, program CTC channel 2 for mode 0,
+	 * (interrupt on terminal count mode), binary count,
+	 * load maximum divisor we can get for accuracy - 65535
+	 */
+	
+	outb(0xb0, 0x43);	/* binary, mode 0, LSB/MSB, Ch 2 */
+	outb(CALIBRATE_DIVISOR & 0xff, 0x42);	/* LSB of count */
+	outb(CALIBRATE_DIVISOR >> 8, 0x42);	/* MSB of count */
+
+	/* we still should not hang if timer not runing or N/A */
+	for (cc = rpcc(); (inb(0x61) & 0x20) == 0 && !(count >> 32); count++);
+
+	/* cycles delta */
+	cc = rpcc() - cc;
+	
+	/* check for the reliable result */
+	if ((count < 1) || (count >> 32))
+	    return 0;
+
+	/* and the final result in HZ */
+	return ((unsigned long)cc * CLOCK_TICK_RATE) / CALIBRATE_DIVISOR;
+}
+
+
 void
 time_init(void)
 {
@@ -239,6 +282,10 @@
 	unsigned long cycle_freq, ppm_error;
 	long diff;
 
+	/* Calibrate CPU clock using CTC. If this fails, use RTC. */
+	if (!est_cycle_freq)
+	    est_cycle_freq = calibrate_cc();
+
 	/*
 	 * The Linux interpretation of the CMOS clock register contents:
 	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
@@ -275,7 +322,7 @@
 	if (diff < 0)
 		diff = -diff;
 	ppm_error = (diff * 1000000L) / cycle_freq;
-#if 0
+#if 1
 	printk("Alpha clock init: HWRPB %lu, Measured %lu, error=%lu ppm.\n",
 	       hwrpb->cycle_freq, est_cycle_freq, ppm_error);
 #endif
alpha/kernel/time.c renamed from alpha/kernel/time.c.orig +15 -31

67 lines not on this page · raw message

#7 lore raw
In reply to Oleg I. Vdovikin

Oleg,

How is this relative to HZ, when you remove all references to HZ?

Quoted 3 lines
(quoted diff) +1 -2
-#define CALIBRATE_LATCH        (52 * LATCH)
-#define CALIBRATE_TIME (52 * 1000020 / HZ)
+#define CALIBRATE_LATCH        0xffff

[...]

Review

Quoted 2 lines
(quoted diff) +2 -0
+       /* and the final result in HZ */
+       return ((unsigned long)cc * CLOCK_TICK_RATE) / CALIBRATE_LATCH;

and in asm-alpha/timex.h,

Quoted 1 line

#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */

Signature · 3 lines
Jeff Garzik      | Thalidomide, eh? 
Building 1024    | So you're saying the eggplant has an accomplice?
MandrakeSoft     |
#8 lore raw
In reply to Oleg I. Vdovikin
Quoted 2 lines · Oleg I. Vdovikin

Richard, thanks. But please use calibrate_cc version which I've submited
as a patch - it gives more accuracy with maximum latch we can ever use and

With both variants even on a 166MHz CPU you'll get above 1e-7 precision, which is way above accuracy of any crystal oscillator.

Quoted 2 lines

has cc's type changed to 'unsigned int' to prevent problems when rpcc overflows.

The only difference is that you'll have extra 'zap' instruction converting 'unsigned int' to 'unsigned long'.

Ivan.

#9 lore raw
In reply to Oleg I. Vdovikin

Jeff,

The things are pretty simple (HZ - in real should be "Hz", cause HZ are
fixed for Alpha, HZ = 1024 Hz) :
Hz = cc / calibration_time

cc == rpcc() at end - rpcc() at begin calibration_time = (CLOCK_TICK_RATE / CALIBRATE_LATCH).

So there is nothing wrong - clock ticks with CLOCK_TICK_RATE and we've a
divisor equal to CALIBRATE_LATCH. So the time interval elapses after (CLOCK_TICK_RATE / CALIBRATE_LATCH) seconds and the CPU performs 'cc' cycles.

That's all. And these really works. ;-))

About x86 style code - don't forget what LATCH defined as follows in
linux/timex.h:

#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */

Regards,
Oleg.

Quoted 19 lines

Oleg,

How is this relative to HZ, when you remove all references to HZ?

Quoted 3 lines
(quoted diff) +1 -2
-#define CALIBRATE_LATCH        (52 * LATCH)
-#define CALIBRATE_TIME (52 * 1000020 / HZ)
+#define CALIBRATE_LATCH        0xffff

[...]

Review

Quoted 2 lines
(quoted diff) +2 -0
+       /* and the final result in HZ */
+       return ((unsigned long)cc * CLOCK_TICK_RATE) / CALIBRATE_LATCH;

and in asm-alpha/timex.h,

Quoted 1 line

#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */

--

Jeff Garzik      | Thalidomide, eh?
Building 1024    | So you're saying the eggplant has an accomplice?
MandrakeSoft     |
#10 lore raw
In reply to Oleg I. Vdovikin
Quoted 2 lines

With both variants even on a 166MHz CPU you'll get above 1e-7 precision, which is way above accuracy of any crystal oscillator.

No, this is not so - this line

return ((long)cc * 1000000) / CALIBRATE_TIME;

truncates the result to the MHZ because of the '* 1000000' statement (cc
is an int value, so you just loose the precision). This works ok for x86, because x86 uses this value with an accuracy to MHz, but this is not enough for Alphas (see gettimeofday - we're relies rpcc for calculation). Try to pass 'cycle=666000000' to your kernel and when run ntp - you're out of luck for clock sync.

But the most innacuracy comes from

#define CALIBRATE_TIME (5 * 1000020/HZ)

    1000020 != CLOCK_TICK_RATE - why? So, with this stuff we're loosing more

than 100 KHz (again, this ok for x86) ....

Quoted 6 lines
Quoted 3 lines

has cc's type changed to 'unsigned int' to prevent problems when rpcc overflows.

The only difference is that you'll have extra 'zap' instruction converting 'unsigned int' to 'unsigned long'.

No, this is not so. The problem is with the sign bit of int, so,

(long)(int)0x80000000 != (long)(unsigned int)0x80000000, and
(long)(int)0x80000000 < 0 and you will get negative frequency value (yes we current boxes we're not overflowing, but let's look for the future). Funny? ;-))

Oleg.

P.S. Ivan, you can reach me by dialing 938-6412 in Moscow.

#11 lore raw
In reply to Oleg I. Vdovikin
Quoted 4 lines · Oleg I. Vdovikin

return ((long)cc * 1000000) / CALIBRATE_TIME;

truncates the result to the MHZ because of the '* 1000000' statement (cc
is an int value, so you just loose the precision).

No, this is ok. 'cc' is long here, and CALIBRATE_TIME is in microseconds, hence '* 1000000'.

Quoted 5 lines

This works ok for x86,
because x86 uses this value with an accuracy to MHz, but this is not enough for Alphas (see gettimeofday - we're relies rpcc for calculation). Try to pass 'cycle=666000000' to your kernel and when run ntp - you're out of luck for clock sync.

Hmm, this should be ok. I heard of people who had problems with ntp starting from 0.5% or more difference between real and estimated clock rates.

Quoted 3 lines

But the most innacuracy comes from

#define CALIBRATE_TIME (5 * 1000020/HZ)

With that I agree. All these integer divisions leads to about %0.02 error.

Quoted 3 lines
    (long)(int)0x80000000 != (long)(unsigned int)0x80000000, and

(long)(int)0x80000000 < 0 and you will get negative frequency value (yes we current boxes we're not overflowing, but let's look for the future).

Oh, I see. So you're arguing for 72 vs. 36 GHz limit. ;-)

Quoted 2 lines

Funny?
;-))

Not at all. The future of Alpha is dark... [thanks, Compaq!]

Quoted 1 line

P.S. Ivan, you can reach me by dialing 938-6412 in Moscow.

Ok. And I can be reached at 930-8952.

Ivan.