2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <linux/bitops.h>
# include <linux/delay.h>
# include <linux/pci.h>
# include <asm/dma.h>
# include <asm/io.h>
2007-07-22 11:12:38 +02:00
# include <asm/processor-cyrix.h>
2005-04-16 15:20:36 -07:00
# include <asm/timer.h>
2007-02-13 13:26:26 +01:00
# include <asm/pci-direct.h>
Detach sched.h from mm.h
First thing mm.h does is including sched.h solely for can_do_mlock() inline
function which has "current" dereference inside. By dealing with can_do_mlock()
mm.h can be detached from sched.h which is good. See below, why.
This patch
a) removes unconditional inclusion of sched.h from mm.h
b) makes can_do_mlock() normal function in mm/mlock.c
c) exports can_do_mlock() to not break compilation
d) adds sched.h inclusions back to files that were getting it indirectly.
e) adds less bloated headers to some files (asm/signal.h, jiffies.h) that were
getting them indirectly
Net result is:
a) mm.h users would get less code to open, read, preprocess, parse, ... if
they don't need sched.h
b) sched.h stops being dependency for significant number of files:
on x86_64 allmodconfig touching sched.h results in recompile of 4083 files,
after patch it's only 3744 (-8.3%).
Cross-compile tested on
all arm defconfigs, all mips defconfigs, all powerpc defconfigs,
alpha alpha-up
arm
i386 i386-up i386-defconfig i386-allnoconfig
ia64 ia64-up
m68k
mips
parisc parisc-up
powerpc powerpc-up
s390 s390-up
sparc sparc-up
sparc64 sparc64-up
um-x86_64
x86_64 x86_64-up x86_64-defconfig x86_64-allnoconfig
as well as my two usual configs.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-21 01:22:52 +04:00
# include <asm/tsc.h>
2005-04-16 15:20:36 -07:00
# include "cpu.h"
/*
* Read NSC / Cyrix DEVID registers ( DIR ) to get more detailed info . about the CPU
*/
2006-09-26 10:52:36 +02:00
static void __cpuinit do_cyrix_devid ( unsigned char * dir0 , unsigned char * dir1 )
2005-04-16 15:20:36 -07:00
{
unsigned char ccr2 , ccr3 ;
unsigned long flags ;
/* we test for DEVID by checking whether CCR3 is writable */
local_irq_save ( flags ) ;
ccr3 = getCx86 ( CX86_CCR3 ) ;
setCx86 ( CX86_CCR3 , ccr3 ^ 0x80 ) ;
getCx86 ( 0xc0 ) ; /* dummy to change bus */
if ( getCx86 ( CX86_CCR3 ) = = ccr3 ) { /* no DEVID regs. */
ccr2 = getCx86 ( CX86_CCR2 ) ;
setCx86 ( CX86_CCR2 , ccr2 ^ 0x04 ) ;
getCx86 ( 0xc0 ) ; /* dummy */
if ( getCx86 ( CX86_CCR2 ) = = ccr2 ) /* old Cx486SLC/DLC */
* dir0 = 0xfd ;
else { /* Cx486S A step */
setCx86 ( CX86_CCR2 , ccr2 ) ;
* dir0 = 0xfe ;
}
}
else {
setCx86 ( CX86_CCR3 , ccr3 ) ; /* restore CCR3 */
/* read DIR0 and DIR1 CPU registers */
* dir0 = getCx86 ( CX86_DIR0 ) ;
* dir1 = getCx86 ( CX86_DIR1 ) ;
}
local_irq_restore ( flags ) ;
}
/*
* Cx86_dir0_msb is a HACK needed by check_cx686_cpuid / slop in bugs . h in
* order to identify the Cyrix CPU model after we ' re out of setup . c
*
* Actually since bugs . h doesn ' t even reference this perhaps someone should
* fix the documentation ? ? ?
*/
2006-09-26 10:52:36 +02:00
static unsigned char Cx86_dir0_msb __cpuinitdata = 0 ;
2005-04-16 15:20:36 -07:00
2006-09-26 10:52:36 +02:00
static char Cx86_model [ ] [ 9 ] __cpuinitdata = {
2005-04-16 15:20:36 -07:00
" Cx486 " , " Cx486 " , " 5x86 " , " 6x86 " , " MediaGX " , " 6x86MX " ,
" M II " , " Unknown "
} ;
2006-09-26 10:52:36 +02:00
static char Cx486_name [ ] [ 5 ] __cpuinitdata = {
2005-04-16 15:20:36 -07:00
" SLC " , " DLC " , " SLC2 " , " DLC2 " , " SRx " , " DRx " ,
" SRx2 " , " DRx2 "
} ;
2006-09-26 10:52:36 +02:00
static char Cx486S_name [ ] [ 4 ] __cpuinitdata = {
2005-04-16 15:20:36 -07:00
" S " , " S2 " , " Se " , " S2e "
} ;
2006-09-26 10:52:36 +02:00
static char Cx486D_name [ ] [ 4 ] __cpuinitdata = {
2005-04-16 15:20:36 -07:00
" DX " , " DX2 " , " ? " , " ? " , " ? " , " DX4 "
} ;
2006-09-26 10:52:36 +02:00
static char Cx86_cb [ ] __cpuinitdata = " ?.5x Core/Bus Clock " ;
static char cyrix_model_mult1 [ ] __cpuinitdata = " 12??43 " ;
static char cyrix_model_mult2 [ ] __cpuinitdata = " 12233445 " ;
2005-04-16 15:20:36 -07:00
/*
* Reset the slow - loop ( SLOP ) bit on the 686 ( L ) which is set by some old
* BIOSes for compatibility with DOS games . This makes the udelay loop
* work correctly , and improves performance .
*
* FIXME : our newer udelay uses the tsc . We don ' t need to frob with SLOP
*/
extern void calibrate_delay ( void ) __init ;
2006-09-26 10:52:36 +02:00
static void __cpuinit check_cx686_slop ( struct cpuinfo_x86 * c )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
if ( Cx86_dir0_msb = = 3 ) {
unsigned char ccr3 , ccr5 ;
local_irq_save ( flags ) ;
ccr3 = getCx86 ( CX86_CCR3 ) ;
setCx86 ( CX86_CCR3 , ( ccr3 & 0x0f ) | 0x10 ) ; /* enable MAPEN */
ccr5 = getCx86 ( CX86_CCR5 ) ;
if ( ccr5 & 2 )
setCx86 ( CX86_CCR5 , ccr5 & 0xfd ) ; /* reset SLOP */
setCx86 ( CX86_CCR3 , ccr3 ) ; /* disable MAPEN */
local_irq_restore ( flags ) ;
if ( ccr5 & 2 ) { /* possible wrong calibration done */
printk ( KERN_INFO " Recalibrating delay loop with SLOP bit reset \n " ) ;
calibrate_delay ( ) ;
c - > loops_per_jiffy = loops_per_jiffy ;
}
}
}
2006-09-26 10:52:36 +02:00
static void __cpuinit set_cx86_reorder ( void )
2005-04-16 15:20:36 -07:00
{
u8 ccr3 ;
printk ( KERN_INFO " Enable Memory access reorder on Cyrix/NSC processor. \n " ) ;
ccr3 = getCx86 ( CX86_CCR3 ) ;
setCx86 ( CX86_CCR3 , ( ccr3 & 0x0f ) | 0x10 ) ; /* enable MAPEN<45> */
/* Load/Store Serialize to mem access disable (=reorder it)<29> */
setCx86 ( CX86_PCR0 , getCx86 ( CX86_PCR0 ) & ~ 0x80 ) ;
/* set load/store serialize from 1GB to 4GB */
ccr3 | = 0xe0 ;
setCx86 ( CX86_CCR3 , ccr3 ) ;
}
2006-09-26 10:52:36 +02:00
static void __cpuinit set_cx86_memwb ( void )
2005-04-16 15:20:36 -07:00
{
u32 cr0 ;
printk ( KERN_INFO " Enable Memory-Write-back mode on Cyrix/NSC processor. \n " ) ;
/* CCR2 bit 2: unlock NW bit */
setCx86 ( CX86_CCR2 , getCx86 ( CX86_CCR2 ) & ~ 0x04 ) ;
/* set 'Not Write-through' */
cr0 = 0x20000000 ;
2005-09-03 15:56:36 -07:00
write_cr0 ( read_cr0 ( ) | cr0 ) ;
2005-04-16 15:20:36 -07:00
/* CCR2 bit 2: lock NW bit and set WT1 */
setCx86 ( CX86_CCR2 , getCx86 ( CX86_CCR2 ) | 0x14 ) ;
}
2006-09-26 10:52:36 +02:00
static void __cpuinit set_cx86_inc ( void )
2005-04-16 15:20:36 -07:00
{
unsigned char ccr3 ;
printk ( KERN_INFO " Enable Incrementor on Cyrix/NSC processor. \n " ) ;
ccr3 = getCx86 ( CX86_CCR3 ) ;
setCx86 ( CX86_CCR3 , ( ccr3 & 0x0f ) | 0x10 ) ; /* enable MAPEN<45> */
/* PCR1 -- Performance Control */
/* Incrementor on, whatever that is */
setCx86 ( CX86_PCR1 , getCx86 ( CX86_PCR1 ) | 0x02 ) ;
/* PCR0 -- Performance Control */
/* Incrementor Margin 10 */
setCx86 ( CX86_PCR0 , getCx86 ( CX86_PCR0 ) | 0x04 ) ;
setCx86 ( CX86_CCR3 , ccr3 ) ; /* disable MAPEN */
}
/*
* Configure later MediaGX and / or Geode processor .
*/
2006-09-26 10:52:36 +02:00
static void __cpuinit geode_configure ( void )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
2007-02-13 13:26:25 +01:00
u8 ccr3 ;
2005-04-16 15:20:36 -07:00
local_irq_save ( flags ) ;
/* Suspend on halt power saving and enable #SUSP pin */
setCx86 ( CX86_CCR2 , getCx86 ( CX86_CCR2 ) | 0x88 ) ;
ccr3 = getCx86 ( CX86_CCR3 ) ;
2007-02-13 13:26:25 +01:00
setCx86 ( CX86_CCR3 , ( ccr3 & 0x0f ) | 0x10 ) ; /* enable MAPEN */
2005-04-16 15:20:36 -07:00
2007-02-13 13:26:25 +01:00
/* FPU fast, DTE cache, Mem bypass */
setCx86 ( CX86_CCR4 , getCx86 ( CX86_CCR4 ) | 0x38 ) ;
setCx86 ( CX86_CCR3 , ccr3 ) ; /* disable MAPEN */
2005-04-16 15:20:36 -07:00
set_cx86_memwb ( ) ;
set_cx86_reorder ( ) ;
set_cx86_inc ( ) ;
local_irq_restore ( flags ) ;
}
2006-09-26 10:52:36 +02:00
static void __cpuinit init_cyrix ( struct cpuinfo_x86 * c )
2005-04-16 15:20:36 -07:00
{
unsigned char dir0 , dir0_msn , dir0_lsn , dir1 = 0 ;
char * buf = c - > x86_model_id ;
const char * p = NULL ;
/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
3 DNow is IDd by bit 31 in extended CPUID ( 1 * 32 + 31 ) anyway */
clear_bit ( 0 * 32 + 31 , c - > x86_capability ) ;
/* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
if ( test_bit ( 1 * 32 + 24 , c - > x86_capability ) ) {
clear_bit ( 1 * 32 + 24 , c - > x86_capability ) ;
set_bit ( X86_FEATURE_CXMMX , c - > x86_capability ) ;
}
do_cyrix_devid ( & dir0 , & dir1 ) ;
check_cx686_slop ( c ) ;
Cx86_dir0_msb = dir0_msn = dir0 > > 4 ; /* identifies CPU "family" */
dir0_lsn = dir0 & 0xf ; /* model or clock multiplier */
/* common case step number/rev -- exceptions handled below */
c - > x86_model = ( dir1 > > 4 ) + 1 ;
c - > x86_mask = dir1 & 0xf ;
/* Now cook; the original recipe is by Channing Corn, from Cyrix.
* We do the same thing for each generation : we work out
* the model , multiplier and stepping . Black magic included ,
* to make the silicon step / rev numbers match the printed ones .
*/
switch ( dir0_msn ) {
unsigned char tmp ;
case 0 : /* Cx486SLC/DLC/SRx/DRx */
p = Cx486_name [ dir0_lsn & 7 ] ;
break ;
case 1 : /* Cx486S/DX/DX2/DX4 */
p = ( dir0_lsn & 8 ) ? Cx486D_name [ dir0_lsn & 5 ]
: Cx486S_name [ dir0_lsn & 3 ] ;
break ;
case 2 : /* 5x86 */
Cx86_cb [ 2 ] = cyrix_model_mult1 [ dir0_lsn & 5 ] ;
p = Cx86_cb + 2 ;
break ;
case 3 : /* 6x86/6x86L */
Cx86_cb [ 1 ] = ' ' ;
Cx86_cb [ 2 ] = cyrix_model_mult1 [ dir0_lsn & 5 ] ;
if ( dir1 > 0x21 ) { /* 686L */
Cx86_cb [ 0 ] = ' L ' ;
p = Cx86_cb ;
( c - > x86_model ) + + ;
} else /* 686 */
p = Cx86_cb + 1 ;
/* Emulate MTRRs using Cyrix's ARRs. */
set_bit ( X86_FEATURE_CYRIX_ARR , c - > x86_capability ) ;
/* 6x86's contain this bug */
c - > coma_bug = 1 ;
break ;
case 4 : /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
# ifdef CONFIG_PCI
2007-02-13 13:26:26 +01:00
{
u32 vendor , device ;
2005-04-16 15:20:36 -07:00
/* It isn't really a PCI quirk directly, but the cure is the
same . The MediaGX has deep magic SMM stuff that handles the
SB emulation . It thows away the fifo on disable_dma ( ) which
is wrong and ruins the audio .
Bug2 : VSA1 has a wrap bug so that using maximum sized DMA
causes bad things . According to NatSemi VSA2 has another
bug to do with ' hlt ' . I ' ve not seen any boards using VSA2
and X doesn ' t seem to support it either so who cares 8 ) .
VSA1 we work around however .
*/
printk ( KERN_INFO " Working around Cyrix MediaGX virtual DMA bugs. \n " ) ;
isa_dma_bridge_buggy = 2 ;
2006-06-23 02:04:26 -07:00
2007-02-13 13:26:26 +01:00
/* We do this before the PCI layer is running. However we
are safe here as we know the bridge must be a Cyrix
companion and must be present */
vendor = read_pci_config_16 ( 0 , 0 , 0x12 , PCI_VENDOR_ID ) ;
device = read_pci_config_16 ( 0 , 0 , 0x12 , PCI_DEVICE_ID ) ;
2006-06-23 02:04:26 -07:00
2005-04-16 15:20:36 -07:00
/*
* The 5510 / 5520 companion chips have a funky PIT .
*/
2007-02-13 13:26:26 +01:00
if ( vendor = = PCI_VENDOR_ID_CYRIX & &
( device = = PCI_DEVICE_ID_CYRIX_5510 | | device = = PCI_DEVICE_ID_CYRIX_5520 ) )
2007-05-02 19:27:08 +02:00
mark_tsc_unstable ( " cyrix 5510/5520 detected " ) ;
2007-02-13 13:26:26 +01:00
}
2006-06-23 02:04:26 -07:00
# endif
c - > x86_cache_size = 16 ; /* Yep 16K integrated cache thats it */
2005-04-16 15:20:36 -07:00
/* GXm supports extended cpuid levels 'ala' AMD */
if ( c - > cpuid_level = = 2 ) {
/* Enable cxMMX extensions (GX1 Datasheet 54) */
2007-02-13 13:26:24 +01:00
setCx86 ( CX86_CCR7 , getCx86 ( CX86_CCR7 ) | 1 ) ;
2005-04-16 15:20:36 -07:00
2007-02-13 13:26:24 +01:00
/*
* GXm : 0x30 . . . 0x5f GXm datasheet 51
* GXlv : 0x6 x GXlv datasheet 54
* ? : 0x7 x
* GX1 : 0x8 x GX1 datasheet 56
*/
if ( ( 0x30 < = dir1 & & dir1 < = 0x6f ) | | ( 0x80 < = dir1 & & dir1 < = 0x8f ) )
2005-04-16 15:20:36 -07:00
geode_configure ( ) ;
get_model_name ( c ) ; /* get CPU marketing name */
return ;
}
else { /* MediaGX */
Cx86_cb [ 2 ] = ( dir0_lsn & 1 ) ? ' 3 ' : ' 4 ' ;
p = Cx86_cb + 2 ;
c - > x86_model = ( dir1 & 0x20 ) ? 1 : 2 ;
}
break ;
case 5 : /* 6x86MX/M II */
if ( dir1 > 7 )
{
dir0_msn + + ; /* M II */
/* Enable MMX extensions (App note 108) */
setCx86 ( CX86_CCR7 , getCx86 ( CX86_CCR7 ) | 1 ) ;
}
else
{
c - > coma_bug = 1 ; /* 6x86MX, it has the bug. */
}
tmp = ( ! ( dir0_lsn & 7 ) | | dir0_lsn & 1 ) ? 2 : 0 ;
Cx86_cb [ tmp ] = cyrix_model_mult2 [ dir0_lsn & 7 ] ;
p = Cx86_cb + tmp ;
if ( ( ( dir1 & 0x0f ) > 4 ) | | ( ( dir1 & 0xf0 ) = = 0x20 ) )
( c - > x86_model ) + + ;
/* Emulate MTRRs using Cyrix's ARRs. */
set_bit ( X86_FEATURE_CYRIX_ARR , c - > x86_capability ) ;
break ;
case 0xf : /* Cyrix 486 without DEVID registers */
switch ( dir0_lsn ) {
case 0xd : /* either a 486SLC or DLC w/o DEVID */
dir0_msn = 0 ;
p = Cx486_name [ ( c - > hard_math ) ? 1 : 0 ] ;
break ;
case 0xe : /* a 486S A step */
dir0_msn = 0 ;
p = Cx486S_name [ 0 ] ;
break ;
}
break ;
default : /* unknown (shouldn't happen, we know everyone ;-) */
dir0_msn = 7 ;
break ;
}
strcpy ( buf , Cx86_model [ dir0_msn & 7 ] ) ;
if ( p ) strcat ( buf , p ) ;
return ;
}
2006-01-06 00:12:14 -08:00
/*
* Handle National Semiconductor branded processors
*/
2006-09-26 10:52:36 +02:00
static void __cpuinit init_nsc ( struct cpuinfo_x86 * c )
2006-01-06 00:12:14 -08:00
{
/* There may be GX1 processors in the wild that are branded
* NSC and not Cyrix .
*
* This function only handles the GX processor , and kicks every
* thing else to the Cyrix init function above - that should
* cover any processors that might have been branded differently
2006-06-26 18:35:02 +02:00
* after NSC acquired Cyrix .
2006-01-06 00:12:14 -08:00
*
* If this breaks your GX1 horribly , please e - mail
* info - linux @ ldcmail . amd . com to tell us .
*/
/* Handle the GX (Formally known as the GX2) */
if ( c - > x86 = = 5 & & c - > x86_model = = 5 )
display_cacheinfo ( c ) ;
else
init_cyrix ( c ) ;
}
2005-04-16 15:20:36 -07:00
/*
* Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
* by the fact that they preserve the flags across the division of 5 / 2.
* PII and PPro exhibit this behavior too , but they have cpuid available .
*/
/*
* Perform the Cyrix 5 / 2 test . A Cyrix won ' t change
* the flags , while other 486 chips will .
*/
static inline int test_cyrix_52div ( void )
{
unsigned int test ;
__asm__ __volatile__ (
" sahf \n \t " /* clear flags (%eax = 0x0005) */
" div %b2 \n \t " /* divide 5 by 2 */
" lahf " /* store flags into %ah */
: " =a " ( test )
: " 0 " ( 5 ) , " q " ( 2 )
: " cc " ) ;
/* AH is 0x02 on Cyrix after the divide.. */
return ( unsigned char ) ( test > > 8 ) = = 0x02 ;
}
2006-09-26 10:52:36 +02:00
static void __cpuinit cyrix_identify ( struct cpuinfo_x86 * c )
2005-04-16 15:20:36 -07:00
{
/* Detect Cyrix with disabled CPUID */
if ( c - > x86 = = 4 & & test_cyrix_52div ( ) ) {
unsigned char dir0 , dir1 ;
strcpy ( c - > x86_vendor_id , " CyrixInstead " ) ;
c - > x86_vendor = X86_VENDOR_CYRIX ;
/* Actually enable cpuid on the older cyrix */
/* Retrieve CPU revisions */
do_cyrix_devid ( & dir0 , & dir1 ) ;
dir0 > > = 4 ;
/* Check it is an affected model */
if ( dir0 = = 5 | | dir0 = = 3 )
{
2007-02-13 13:26:25 +01:00
unsigned char ccr3 ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
printk ( KERN_INFO " Enabling CPUID on Cyrix processor. \n " ) ;
local_irq_save ( flags ) ;
ccr3 = getCx86 ( CX86_CCR3 ) ;
2007-02-13 13:26:25 +01:00
setCx86 ( CX86_CCR3 , ( ccr3 & 0x0f ) | 0x10 ) ; /* enable MAPEN */
setCx86 ( CX86_CCR4 , getCx86 ( CX86_CCR4 ) | 0x80 ) ; /* enable cpuid */
setCx86 ( CX86_CCR3 , ccr3 ) ; /* disable MAPEN */
2005-04-16 15:20:36 -07:00
local_irq_restore ( flags ) ;
}
}
}
2006-09-26 10:52:36 +02:00
static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
2005-04-16 15:20:36 -07:00
. c_vendor = " Cyrix " ,
. c_ident = { " CyrixInstead " } ,
. c_init = init_cyrix ,
. c_identify = cyrix_identify ,
} ;
int __init cyrix_init_cpu ( void )
{
cpu_devs [ X86_VENDOR_CYRIX ] = & cyrix_cpu_dev ;
return 0 ;
}
2006-09-26 10:52:36 +02:00
static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
2005-04-16 15:20:36 -07:00
. c_vendor = " NSC " ,
. c_ident = { " Geode by NSC " } ,
2006-01-06 00:12:14 -08:00
. c_init = init_nsc ,
2005-04-16 15:20:36 -07:00
} ;
int __init nsc_init_cpu ( void )
{
cpu_devs [ X86_VENDOR_NSC ] = & nsc_cpu_dev ;
return 0 ;
}