Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
> 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 * 100) / CALIBRATE_TIME; truncates the result to the MHZ because of the '* 100' 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=66600' 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 * 120/HZ) 120 != CLOCK_TICK_RATE - why? So, with this stuff we're loosing more than 100 KHz (again, this ok for x86) > > > 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)0x8000 != (long)(unsigned int)0x8000, and (long)(int)0x8000 < 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. - 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/
Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
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. > Oleg, > > How is this relative to HZ, when you remove all references to HZ? > > > -#define CALIBRATE_LATCH(52 * LATCH) > > -#define CALIBRATE_TIME (52 * 120 / HZ) > > +#define CALIBRATE_LATCH0x > [...] > > + /* and the final result in HZ */ > > + return ((unsigned long)cc * CLOCK_TICK_RATE) / CALIBRATE_LATCH; > > and in asm-alpha/timex.h, > > #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ > > -- > Jeff Garzik | Thalidomide, eh? > Building 1024| So you're saying the eggplant has an accomplice? > MandrakeSoft | > - 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/
Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
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. Oleg, How is this relative to HZ, when you remove all references to HZ? -#define CALIBRATE_LATCH(52 * LATCH) -#define CALIBRATE_TIME (52 * 120 / HZ) +#define CALIBRATE_LATCH0x [...] + /* and the final result in HZ */ + return ((unsigned long)cc * CLOCK_TICK_RATE) / CALIBRATE_LATCH; and in asm-alpha/timex.h, #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ -- Jeff Garzik | Thalidomide, eh? Building 1024| So you're saying the eggplant has an accomplice? MandrakeSoft | - 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/
Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
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 * 100) / CALIBRATE_TIME; truncates the result to the MHZ because of the '* 100' 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=66600' 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 * 120/HZ) 120 != CLOCK_TICK_RATE - why? So, with this stuff we're loosing more than 100 KHz (again, this ok for x86) 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)0x8000 != (long)(unsigned int)0x8000, and (long)(int)0x8000 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. - 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/
Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
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? > 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 | > linux-2.2.x.rtc.patch linux-2.4.7pre2.rtc.patch
Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
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? > On Fri, Jun 29, 2001 at 09:19:31PM +0400, Ivan Kokshaysky wrote: > > Good idea. The patch below works reliably on my sx164. > > Reasonable. Here I've cleaned up time_init a tad as well. > > > r~ > > > > --- arch/alpha/kernel/time.c.orig Fri Jun 29 11:24:03 2001 > +++ arch/alpha/kernel/time.c Fri Jun 29 11:35:52 2001 > @@ -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 * 120 / 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 * 100) / 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/ > - 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/
Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
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? On Fri, Jun 29, 2001 at 09:19:31PM +0400, Ivan Kokshaysky wrote: Good idea. The patch below works reliably on my sx164. Reasonable. Here I've cleaned up time_init a tad as well. r~ --- arch/alpha/kernel/time.c.orig Fri Jun 29 11:24:03 2001 +++ arch/alpha/kernel/time.c Fri Jun 29 11:35:52 2001 @@ -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 * 120 / 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 * 100) / 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/ - 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/
Re: [patch] Re: alpha - generic_init_pit - why using RTC for calibration?
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? 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 | linux-2.2.x.rtc.patch linux-2.4.7pre2.rtc.patch
[PATCH] alpha - generic_init_pit - CTC calibration
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. --- linux/arch/alpha/kernel/time.c.orig Mon Jul 2 14:05:09 2001 +++ linux/arch/alpha/kernel/time.c Mon Jul 2 15:47:45 2001 @@ -231,6 +231,49 @@ outb(0x13, 0x42); } +/* + * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from + * arch/i386/time.c. + */ + +#define CALIBRATE_DIVISOR 0x + +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 - 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/
[PATCH] alpha - generic_init_pit - CTC calibration
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. --- linux/arch/alpha/kernel/time.c.orig Mon Jul 2 14:05:09 2001 +++ linux/arch/alpha/kernel/time.c Mon Jul 2 15:47:45 2001 @@ -231,6 +231,49 @@ outb(0x13, 0x42); } +/* + * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from + * arch/i386/time.c. + */ + +#define CALIBRATE_DIVISOR 0x + +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 - 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/
Re: alpha - generic_init_pit - why using RTC for calibration?
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. --- linux/arch/alpha/kernel/time.c.orig Mon Jul 2 14:05:09 2001 +++ linux/arch/alpha/kernel/time.c Mon Jul 2 15:47:45 2001 @@ -231,6 +231,49 @@ outb(0x13, 0x42); } +/* + * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from + * arch/i386/time.c. + */ + +#define CALIBRATE_DIVISOR 0x + +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 linux-2.2.x.rtc.patch
Re: alpha - generic_init_pit - why using RTC for calibration?
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. --- linux/arch/alpha/kernel/time.c.orig Mon Jul 2 14:05:09 2001 +++ linux/arch/alpha/kernel/time.c Mon Jul 2 15:47:45 2001 @@ -231,6 +231,49 @@ outb(0x13, 0x42); } +/* + * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from + * arch/i386/time.c. + */ + +#define CALIBRATE_DIVISOR 0x + +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 linux-2.2.x.rtc.patch
Re: alpha - generic_init_pit - why using RTC for calibration?
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? > On Fri, Jun 29, 2001 at 04:20:59PM +0400, Oleg I. Vdovikin wrote: > > 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... :-( > > > 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. > > --- 2.4.6-pre5/arch/alpha/kernel/time.c Mon Nov 13 06:27:11 2000 > +++ linux/arch/alpha/kernel/time.c Fri Jun 29 20:58:09 2001 > @@ -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 * 120 / 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 * 100) / 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 > - 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/
Re: alpha - generic_init_pit - why using RTC for calibration?
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? On Fri, Jun 29, 2001 at 04:20:59PM +0400, Oleg I. Vdovikin wrote: 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... :-( 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. --- 2.4.6-pre5/arch/alpha/kernel/time.c Mon Nov 13 06:27:11 2000 +++ linux/arch/alpha/kernel/time.c Fri Jun 29 20:58:09 2001 @@ -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 * 120 / 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 * 100) / 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 - 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/
alpha - generic_init_pit - why using RTC for calibration?
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. - 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/
alpha - generic_init_pit - why using RTC for calibration?
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. - 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/
[PATCH] 2.2.19: Alpha PCI code: pcibios_fixup_bus
Hi! We've number of UP2000+ boards (they just like DP264 in common). These boards has 2 PCI hoses, both has 3 PCI slots - one 32bits (IdSel=9) & two 64bits (IdSel=7,8) (6 slots in total). Recently we've tried to install 3c985b 64-bit card and observe the following: this card works just fine being inserted into 32bit slot - detected by Linux PCI code, gots real IRQ level. But we've tried to insert it onto the 64 bit slot we got problems. When inserted onto the slot with IdSel = 8 it's detected twice (!!!) - with IdSels 8 & 13! So, when pci code assign irqs & memory region it's do this twice - firstly for card with IdSel = 8 (which is "real" card and it gots "real" IRQ) and secondly for "phantom" with IdSel = 13 (and assigns IRQ 0 for it because DP264 knows nothing about IdSel 13). As the result 3c985 driver - acenic module sees 2 cards - the real card with valid IRQ (acenic read IRQ from kernel, not from card), but with invalid memory region (because this card was remaped for IdSel 13), and the second card with valid memory region, but with invalid IRQ == 0. Acenic when initialize "phantom", but works very slow... More fun comes when this card inserted onto the slot with IdSel = 7 - it's gets detected 32 times - with IdSel = 0..31 - i.e. entire pci bus! SRM detects this card only 6 times when IdSel = 7 and only once for IdSel = 8, 9 (but SRM knows which IdSels are valid on DP264).. So as seems 64bit 3c985b hardware is not fully comaptible with DP264. We've observe sismilar problems with Intel's EtherExpress PRO/1000 - it's also detected twice with IdSel = 7,12 when inserted onto the slot with IdSel = 7. -- lspci -- for Intel - Note device 01:0c.0 has no IRQ (i.e. IRQ == 0) 01:07.0 Ethernet controller: Intel Corporation: Unknown device 1001 (rev 02) Subsystem: Intel Corporation: Unknown device 1003 Flags: bus master, 66Mhz, medium devsel, latency 252, IRQ 47 Memory at 00010900 (32-bit, non-prefetchable) Memory at 00010902 (32-bit, non-prefetchable) Expansion ROM at 0103 [disabled] Capabilities: [dc] Power Management version 2 01:0c.0 Ethernet controller: Intel Corporation: Unknown device 1001 (rev 02) Subsystem: Intel Corporation: Unknown device 1003 Flags: bus master, 66Mhz, medium devsel, latency 252 Memory at 00010904 (32-bit, non-prefetchable) Memory at 00010906 (32-bit, non-prefetchable) Expansion ROM at 0103 [disabled] -- Sorry, for my bad english and explanations. Attached please find a patch against 2.2.16 - 2.2.19 kernels. This patch alters 3 files: include/asm-alpha/machvec.h - added new function to mv - pci_fixup_bus - just like X86 has, arch/alpha/kernel/bios32.c - added a in the pcibios_fixup_bus - to call a function from mv if any, arch/alpha/kernel/sys_dp264.c - dp264_pci_fixup_bus to disable phantoms. With this patch everything works just fine for me and we got really fast net. ;-)) -- lspci -vv 01:08.0 Ethernet controller: 3Com Corporation 3c985 1000BaseSX (rev 01) Subsystem: Unknown device 9850:0001 Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- Status: Cap- 66Mhz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- SERR- linux-2.2.19.dp264.patch
[PATCH] 2.2.19: Alpha PCI code: pcibios_fixup_bus
Hi! We've number of UP2000+ boards (they just like DP264 in common). These boards has 2 PCI hoses, both has 3 PCI slots - one 32bits (IdSel=9) two 64bits (IdSel=7,8) (6 slots in total). Recently we've tried to install 3c985b 64-bit card and observe the following: this card works just fine being inserted into 32bit slot - detected by Linux PCI code, gots real IRQ level. But we've tried to insert it onto the 64 bit slot we got problems. When inserted onto the slot with IdSel = 8 it's detected twice (!!!) - with IdSels 8 13! So, when pci code assign irqs memory region it's do this twice - firstly for card with IdSel = 8 (which is real card and it gots real IRQ) and secondly for phantom with IdSel = 13 (and assigns IRQ 0 for it because DP264 knows nothing about IdSel 13). As the result 3c985 driver - acenic module sees 2 cards - the real card with valid IRQ (acenic read IRQ from kernel, not from card), but with invalid memory region (because this card was remaped for IdSel 13), and the second card with valid memory region, but with invalid IRQ == 0. Acenic when initialize phantom, but works very slow... More fun comes when this card inserted onto the slot with IdSel = 7 - it's gets detected 32 times - with IdSel = 0..31 - i.e. entire pci bus! SRM detects this card only 6 times when IdSel = 7 and only once for IdSel = 8, 9 (but SRM knows which IdSels are valid on DP264).. So as seems 64bit 3c985b hardware is not fully comaptible with DP264. We've observe sismilar problems with Intel's EtherExpress PRO/1000 - it's also detected twice with IdSel = 7,12 when inserted onto the slot with IdSel = 7. -- lspci -- for Intel - Note device 01:0c.0 has no IRQ (i.e. IRQ == 0) 01:07.0 Ethernet controller: Intel Corporation: Unknown device 1001 (rev 02) Subsystem: Intel Corporation: Unknown device 1003 Flags: bus master, 66Mhz, medium devsel, latency 252, IRQ 47 Memory at 00010900 (32-bit, non-prefetchable) Memory at 00010902 (32-bit, non-prefetchable) Expansion ROM at 0103 [disabled] Capabilities: [dc] Power Management version 2 01:0c.0 Ethernet controller: Intel Corporation: Unknown device 1001 (rev 02) Subsystem: Intel Corporation: Unknown device 1003 Flags: bus master, 66Mhz, medium devsel, latency 252 Memory at 00010904 (32-bit, non-prefetchable) Memory at 00010906 (32-bit, non-prefetchable) Expansion ROM at 0103 [disabled] -- Sorry, for my bad english and explanations. Attached please find a patch against 2.2.16 - 2.2.19 kernels. This patch alters 3 files: include/asm-alpha/machvec.h - added new function to mv - pci_fixup_bus - just like X86 has, arch/alpha/kernel/bios32.c - added a in the pcibios_fixup_bus - to call a function from mv if any, arch/alpha/kernel/sys_dp264.c - dp264_pci_fixup_bus to disable phantoms. With this patch everything works just fine for me and we got really fast net. ;-)) -- lspci -vv 01:08.0 Ethernet controller: 3Com Corporation 3c985 1000BaseSX (rev 01) Subsystem: Unknown device 9850:0001 Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- Status: Cap- 66Mhz+ UDF- FastB2B+ ParErr- DEVSEL=medium TAbort- TAbort- MAbort- SERR- PERR- Latency: 64 min, 248 set, cache line size 08 Interrupt: pin A routed to IRQ 43 Region 0: Memory at 00010900 (32-bit, non-prefetchable) -- As seems pci_fixup_bus needed for Alphas too... And possibly it's need to be done for 2.4 also. Regards, Oleg. linux-2.2.19.dp264.patch