lkml.org 
[lkml]   [2002]   [Oct]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subjectworkaround for Cyrix MediaGX/NSC Geode companion CS5510/5520 PIT latch bug k$vdp(%!_|7x7Ht)^ih5\%\l'hcl$`sqp;%`boxPHDJB<~Sr8(e:zPKmeZ)ZPml[0v\|[V00Jm G,%5V5X9Mw7j}(8+!o>&&wmQ]Xh=j
Date
Hello,

Cyrix MediaGX/NSC Geode is a NatSemi's i386 CPU.
It's old integrated southbrige companion chip cs5510/5520 has a PIT latch bug.
this breaks TSC syncronization, but I found work around about this.

After I posted lkml about this bug in Mar. 2002, I have tried to make this smart.

In past post, I say the dual calling of 'calibrate_tsc()' make things good.
but now I found the simple solution.

This PIT need the delay after 1st counter reset.

in timer_tsc.c,

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 */

is changed to

outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb_p(CALIBRATE_LATCH >> 8, 0x42); /* add delay to start count */


this 'outb_p()' fixes this problem on startup.

The same kind of problem exist in do_gettimeofday().
if we disables TSC on PC using Geode/CS5520, latch value of PIT has no
accuracy then many many timejumps or timebacks happens. (every 2-10 sec)

with this patch, timejumps or timebacks don't occurs.
This patch also removes dodgy_tsc() workaround.

this patch tried on mini note-PC CASSIOPEIA FIVA http://www.casio.co.jp/mpc/103/
you can get spec from http://www.da-cha.org/fiva/fiva.html

I use with this workaround on 6 month and i think this work fine.
I tried 2.4.18, 2.4.19, 2.5.43.

------------------------------------------------------------
--- linux-2.5.43-orig/arch/i386/config.in 2002-10-17 13:04:36.000000000 +0900
+++ linux-2.5.43/arch/i386/config.in 2002-10-17 13:02:44.000000000 +0900
@@ -30,6 +30,7 @@
Winchip-C6 CONFIG_MWINCHIPC6 \
Winchip-2 CONFIG_MWINCHIP2 \
Winchip-2A/Winchip-3 CONFIG_MWINCHIP3D \
+ MediaGX/Geode CONFIG_GEODE \
CyrixIII/VIA-C3 CONFIG_MCYRIXIII" Pentium-Pro
#
# Define implied options from the CPU selection here
@@ -67,6 +68,13 @@
define_bool CONFIG_X86_PPRO_FENCE y
define_bool CONFIG_X86_F00F_BUG y
fi
+if [ "$CONFIG_GEODE" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_SHIFT 5
+ define_bool CONFIG_X86_USE_STRING_486 y
+ define_bool CONFIG_X86_ALIGNMENT_16 y
+ define_bool CONFIG_X86_TSC y
+ define_bool CONFIG_X86_PPRO_FENCE y
+fi
if [ "$CONFIG_M586TSC" = "y" ]; then
define_int CONFIG_X86_L1_CACHE_SHIFT 5
define_bool CONFIG_X86_USE_STRING_486 y
diff -urB -x .config -x '*.[oasS]' -x '*.in' -x '*.rej' -x '*.orig' linux-2.5.43-orig/arch/i386/kernel/cpu/common.c linux-2.5.43/arch/i386/kernel/cpu/common.c
--- linux-2.5.43-orig/arch/i386/kernel/cpu/common.c 2002-10-12 13:21:05.000000000 +0900
+++ linux-2.5.43/arch/i386/kernel/cpu/common.c 2002-10-14 20:40:46.000000000 +0900
@@ -356,17 +356,6 @@
boot_cpu_data.x86_capability[2],
boot_cpu_data.x86_capability[3]);
}
-/*
- * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
- */
-
-void __init dodgy_tsc(void)
-{
- get_cpu_vendor(&boot_cpu_data);
- if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
- ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC ))
- cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
-}

void __init print_cpu_info(struct cpuinfo_x86 *c)
{
Only in linux-2.5.43/arch/i386/kernel/cpu: common.c~
diff -urB -x .config -x '*.[oasS]' -x '*.in' -x '*.rej' -x '*.orig' linux-2.5.43-orig/arch/i386/kernel/cpu/cyrix.c linux-2.5.43/arch/i386/kernel/cpu/cyrix.c
--- linux-2.5.43-orig/arch/i386/kernel/cpu/cyrix.c 2002-10-12 13:21:34.000000000 +0900
+++ linux-2.5.43/arch/i386/kernel/cpu/cyrix.c 2002-10-14 21:34:57.000000000 +0900
@@ -170,7 +233,7 @@
c->coma_bug = 1;
break;

- case 4: /* MediaGX/GXm */
+ case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
#ifdef CONFIG_PCI
/* It isn't really a PCI quirk directly, but the cure is the
same. The MediaGX has deep magic SMM stuff that handles the
@@ -188,29 +247,26 @@
isa_dma_bridge_buggy = 2;
#endif
c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
+
+ /*
+ * The 5510/5520 companion chips have a funky PIT.
+ */
+ if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) ||
+ pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL))
+ pit_latch_buggy = 1;

/* GXm supports extended cpuid levels 'ala' AMD */
if (c->cpuid_level == 2) {
- /* Enable Natsemi MMX extensions */
- setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
+ /* Enable cxMMX extensions (GX1 Datasheet 54) */
+ setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);

get_model_name(c); /* get CPU marketing name */
- /*
- * The 5510/5520 companion chips have a funky PIT
- * that breaks the TSC synchronizing, so turn it off
- */
- if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) ||
- pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL))
- clear_bit(X86_FEATURE_TSC, c->x86_capability);
return;
}
else { /* MediaGX */
Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
p = Cx86_cb+2;
c->x86_model = (dir1 & 0x20) ? 1 : 2;
-#ifndef CONFIG_CS5520
- clear_bit(X86_FEATURE_TSC, c->x86_capability);
-#endif
}
break;

diff -urB -x .config -x '*.[oasS]' -x '*.in' -x '*.rej' -x '*.orig' linux-2.5.43-orig/arch/i386/kernel/time.c linux-2.5.43/arch/i386/kernel/time.c
--- linux-2.5.43-orig/arch/i386/kernel/time.c 2002-10-17 13:04:36.000000000 +0900
+++ linux-2.5.43/arch/i386/kernel/time.c 2002-10-17 13:02:44.000000000 +0900
@@ -61,6 +61,7 @@
#include <asm/arch_hooks.h>

extern spinlock_t i8259A_lock;
+int pit_latch_buggy; /* extern */

#include "do_timer.h"

diff -urB -x .config -x '*.[oasS]' -x '*.in' -x '*.rej' -x '*.orig' linux-2.5.43-orig/arch/i386/kernel/timers/timer_tsc.c linux-2.5.43/arch/i386/kernel/timers/timer_tsc.c
--- linux-2.5.43-orig/arch/i386/kernel/timers/timer_tsc.c 2002-10-17 13:04:36.000000000 +0900
+++ linux-2.5.43/arch/i386/kernel/timers/timer_tsc.c 2002-10-17 13:02:45.000000000 +0900
@@ -60,6 +60,10 @@
static void mark_offset_tsc(void)
{
int count;
+#ifdef CONFIG_GEODE
+ int countmp;
+ static int count1=0, count2=LATCH;
+#endif
/*
* It is important that these two operations happen almost at
* the same time. We do the RDTSC stuff first, since it's
@@ -83,6 +87,22 @@
count |= inb(0x40) << 8;
spin_unlock(&i8253_lock);

+#ifdef CONFIG_GEODE
+ if (pit_latch_buggy) {
+ /* get center value of last 3 time lutch */
+ if (count2 >= count && count >= count1
+ || count1 >= count && count >= count2) {
+ count2 = count1; count1 = count;
+ } else if (count1 >= count2 && count2 >= count
+ || count >= count2 && count2 >= count1) {
+ countmp = count;count = count2;
+ count2 = count1;count1 = countmp;
+ } else {
+ count2 = count1; count1 = count; count = count1;
+ }
+ }
+#endif
+
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
@@ -114,7 +134,11 @@
*/
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 */
+#ifndef CONFIG_GEODE
+ outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
+#else
+ outb_p(CALIBRATE_LATCH >> 8, 0x42); /* add delay to start count */
+#endif

{
unsigned long startlow, starthigh;
@@ -238,8 +262,6 @@
* moaned if you have the only one in the world - you fix it!
*/

- dodgy_tsc();
-
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
if (tsc_quotient) {
--
Hiroshi Miura --- http://www.da-cha.org/
NTTDATA Corp. Marketing & Business Strategy Planning Dept. --- miurahr@nttdata.co.jp
Key fingerprint = 9117 9407 5684 FBF1 4063 15B4 401D D077 04AB 8617
-- My hacking life is happy as the day is long

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

\
 
 \ /
  Last update: 2005-03-22 13:30    [W:0.065 / U:0.208 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site