Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Tue, 5 Feb 2002 21:20:57 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Tue, 5 Feb 2002 21:20:48 -0500 Received: from ylug.mozilla.gr.jp ([203.141.142.92]:60424 "HELO maison.kyo-ko.org") by vger.kernel.org with SMTP id ; Tue, 5 Feb 2002 21:20:32 -0500 X-Mailer: cmail 2.61.1+20011011 on GNU Emacs 20.7.2 / Mule 4.1 =?ISO-2022-JP?B?KBskQjAqGyhCKQ==?= From: Hiroshi MIURA To: linux-kernel@vger.kernel.org Subject: [PATCH] NSC Geode Companion chip workaround User-Agent: SEMI/1.14.3 (=?ISO-2022-JP?B?GyRCNW0lTkMrGyhC?=) FLIM/1.14.3 (=?ISO-2022-JP?B?GyRCQCZLNThmTk1BMBsoQg==?=) APEL/10.3 Emacs/20.7 (i386-debian-linux-gnu) MULE/4.1 (=?ISO-2022-JP?B?GyRCMCobKEI=?=) MIME-Version: 1.0 (generated by SEMI 1.14.3 - =?ISO-2022-JP?B?IhskQjVtGyhC?= =?ISO-2022-JP?B?GyRCJU5DKxsoQiI=?=) Content-Type: text/plain; charset=US-ASCII Message-Id: <20020206022016.735C7118231@triton2> Date: Wed, 6 Feb 2002 11:20:16 +0900 (JST) Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Cyrix MediaGX/GXm or NSC Geode have PIT bug not TSC bug. but in linux kernel, if CPU is Cyrix, then TSC flag is disabled. This is not correct way, I think. A patch atached below is originally from NetBSD kernel code. In FreeBSD bug tracking system, this was discussed. http://www.freebsd.org/cgi/query-pr.cgi?pr=6630 Here is NetBSD patch. http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=8654 in this patch, this code is activate only if you defines CONFIG_CS5520. I've tryed several month with this patch, It seems good for me. trial machine: Casio CASSIOPEIA FIVA 101 and Fiva 103. MediaGX 200MHz and NSC Geode 300MHz. diff -ur kernel-source-2.4.7/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- kernel-source-2.4.7/arch/i386/kernel/setup.c Thu Jul 12 01:31:44 2001 +++ linux/arch/i386/kernel/setup.c Fri Aug 10 21:12:06 2001 @@ -1425,14 +1425,18 @@ /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { get_model_name(c); /* get CPU marketing name */ +#ifndef CONFIG_CS5520 clear_bit(X86_FEATURE_TSC, c->x86_capability); +#endif 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 -ur kernel-source-2.4.7/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c --- kernel-source-2.4.7/arch/i386/kernel/time.c Sat Dec 30 07:07:57 2000 +++ linux/arch/i386/kernel/time.c Fri Aug 10 21:04:26 2001 @@ -28,6 +28,9 @@ * 1998-12-24 Copyright (C) 1998 Andrea Arcangeli * Fixed a xtime SMP race (we need the xtime_lock rw spinlock to * serialize accesses to xtime/lost_ticks). + * 2001-02-20 Hiroshi Miura + * Work around for Cyrix/IBM/NSC MediaGX/GXm, NSC Geode southbridge + * PIT bug. (NSC Cx5510/5520) */ #include @@ -459,6 +462,10 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int count; +#ifdef CONFIG_CS5520 + int count1, count2, count3; + int n1, n2, n3; +#endif /* * Here we are in the timer irq handler. We just have irqs locally @@ -487,6 +494,7 @@ rdtscl(last_tsc_low); +#ifndef CONFIG_CS5520 spin_lock(&i8253_lock); outb_p(0x00, 0x43); /* latch the count ASAP */ @@ -499,6 +507,59 @@ } do_timer_interrupt(irq, NULL, regs); +#else + spin_lock(&i8253_lock); + outb_p(0x00, 0x43); /* latch the count ASAP */ +/* this codes comes from FreeBSD */ + count1 = inb_p(0x40); + count1 |= inb(0x40) << 8; + count2 = inb_p(0x40); + count2 = inb(0x40) << 8; + count3 = inb_p(0x40); + count3 = inb(0x40) << 8; + spin_unlock(&i8253_lock); + + if (count1 >= count2 && count2 >= count3 && count1 - count2 < 0x200) + count = count2; + else { + +#define _swap_val(a, b) do { \ + int c = a;\ + a = b; \ + b = c; \ +} while(0) + /* sort values */ + if (count1 < count2) + _swap_val(count1, count2); + if (count2 < count3) + _swap_val(count2, count3); + if (count1 < count2) + _swap_val(count1, count2); + + /* compare the middle value */ + if (count1 - count3 < 0x200) + count = count2; + else + { + n1 = count2 - count3; + n2 = count3 - count1 + LATCH; + n3 = count1 - count2; + count = count3; + if (n1 >= n2) { + if (n1 >= n3) + count = count1; + } else { + if (n2 >= n3) + count = count2; + } + } + } + count = ((LATCH-1) - count) * TICK_SIZE; + delay_at_last_interrupt = (count + LATCH/2) / LATCH; + } + + do_timer_interrupt(irq, NULL, regs); +#endif write_unlock(&xtime_lock); @@ -659,6 +720,9 @@ if (cpu_has_tsc) { unsigned long tsc_quotient = calibrate_tsc(); +#ifdef CONFIG_CS5520 + if (!tsc_quotient) tsc_quotient = calibrate_tsc(); +#endif if (tsc_quotient) { fast_gettimeoffset_quotient = tsc_quotient; use_tsc = 1; Hiroshi Miura --- miura@da-cha.org http://www.da-cha.org/ CCNA, Oracle Silver Master, Network Specialist(JITEC) My interest: http://www.cis.com.tw/Product/WS-U50R.htm - 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/