2005-04-17 02:20:36 +04:00
/*
* This file contains work - arounds for many known PCI hardware
* bugs . Devices present only on certain architectures ( host
* bridges et cetera ) should be handled in arch - specific code .
*
* Note : any quirks for hotpluggable devices must _NOT_ be declared __init .
*
* Copyright ( c ) 1999 Martin Mares < mj @ ucw . cz >
*
2005-09-24 04:14:37 +04:00
* Init / reset quirks for USB host controllers should be in the
* USB quirks file , where their drivers can access reuse it .
*
2005-04-17 02:20:36 +04:00
* The bridge optimization stuff has been removed . If you really
* have a silly BIOS which is unable to set your host bridge right ,
* use the PowerTweak utility ( see http : //powertweak.sourceforge.net).
*/
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/pci.h>
# include <linux/init.h>
# include <linux/delay.h>
2005-05-27 12:21:50 +04:00
# include <linux/acpi.h>
2007-12-18 00:09:38 +03:00
# include <linux/kallsyms.h>
2008-11-21 07:42:25 +03:00
# include <linux/dmi.h>
2009-03-05 21:57:28 +03:00
# include <linux/pci-aspm.h>
2009-03-16 11:13:39 +03:00
# include <linux/ioport.h>
2005-04-08 09:53:31 +04:00
# include "pci.h"
2005-04-17 02:20:36 +04:00
2008-08-19 12:28:24 +04:00
int isa_dma_bridge_buggy ;
EXPORT_SYMBOL ( isa_dma_bridge_buggy ) ;
int pci_pci_problems ;
EXPORT_SYMBOL ( pci_pci_problems ) ;
int pcie_mch_quirk ;
EXPORT_SYMBOL ( pcie_mch_quirk ) ;
# ifdef CONFIG_PCI_QUIRKS
2009-03-16 11:13:39 +03:00
/*
2009-04-06 05:24:21 +04:00
* This quirk function disables memory decoding and releases memory resources
* of the device specified by kernel ' s boot parameter ' pci = resource_alignment = ' .
2009-03-16 11:13:39 +03:00
* It also rounds up size to specified alignment .
* Later on , the kernel will assign page - aligned memory resource back
2009-04-06 05:24:21 +04:00
* to the device .
2009-03-16 11:13:39 +03:00
*/
static void __devinit quirk_resource_alignment ( struct pci_dev * dev )
{
int i ;
struct resource * r ;
resource_size_t align , size ;
2009-04-06 05:24:21 +04:00
u16 command ;
2009-03-16 11:13:39 +03:00
if ( ! pci_is_reassigndev ( dev ) )
return ;
if ( dev - > hdr_type = = PCI_HEADER_TYPE_NORMAL & &
( dev - > class > > 8 ) = = PCI_CLASS_BRIDGE_HOST ) {
dev_warn ( & dev - > dev ,
" Can't reassign resources to host bridge. \n " ) ;
return ;
}
2009-04-06 05:24:21 +04:00
dev_info ( & dev - > dev ,
" Disabling memory decoding and releasing memory resources. \n " ) ;
pci_read_config_word ( dev , PCI_COMMAND , & command ) ;
command & = ~ PCI_COMMAND_MEMORY ;
pci_write_config_word ( dev , PCI_COMMAND , command ) ;
2009-03-16 11:13:39 +03:00
align = pci_specified_resource_alignment ( dev ) ;
for ( i = 0 ; i < PCI_BRIDGE_RESOURCES ; i + + ) {
r = & dev - > resource [ i ] ;
if ( ! ( r - > flags & IORESOURCE_MEM ) )
continue ;
size = resource_size ( r ) ;
if ( size < align ) {
size = align ;
dev_info ( & dev - > dev ,
" Rounding up size of resource #%d to %#llx. \n " ,
i , ( unsigned long long ) size ) ;
}
r - > end = size - 1 ;
r - > start = 0 ;
}
/* Need to disable bridge's resource window,
* to enable the kernel to reassign new resource
* window later on .
*/
if ( dev - > hdr_type = = PCI_HEADER_TYPE_BRIDGE & &
( dev - > class > > 8 ) = = PCI_CLASS_BRIDGE_PCI ) {
for ( i = PCI_BRIDGE_RESOURCES ; i < PCI_NUM_RESOURCES ; i + + ) {
r = & dev - > resource [ i ] ;
if ( ! ( r - > flags & IORESOURCE_MEM ) )
continue ;
r - > end = resource_size ( r ) - 1 ;
r - > start = 0 ;
}
pci_disable_bridge_window ( dev ) ;
}
}
DECLARE_PCI_FIXUP_HEADER ( PCI_ANY_ID , PCI_ANY_ID , quirk_resource_alignment ) ;
2006-05-09 04:06:09 +04:00
/* The Mellanox Tavor device gives false positive parity errors
* Mark this device with a broken_parity_status , to allow
* PCI scanning code to " skip " this now blacklisted device .
*/
static void __devinit quirk_mellanox_tavor ( struct pci_dev * dev )
{
dev - > broken_parity_status = 1 ; /* This device gives false positives */
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_MELLANOX , PCI_DEVICE_ID_MELLANOX_TAVOR , quirk_mellanox_tavor ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_MELLANOX , PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE , quirk_mellanox_tavor ) ;
2005-04-17 02:20:36 +04:00
/* Deal with broken BIOS'es that neglect to enable passive release,
which can cause problems in combination with the 82441F X / PPro MTRRs */
2006-12-05 02:14:45 +03:00
static void quirk_passive_release ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
struct pci_dev * d = NULL ;
unsigned char dlc ;
/* We have to make sure a particular bit is set in the PIIX3
ISA bridge , so we have to go out and find it . */
while ( ( d = pci_get_device ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82371SB_0 , d ) ) ) {
pci_read_config_byte ( d , 0x82 , & dlc ) ;
if ( ! ( dlc & 1 < < 1 ) ) {
2008-12-02 01:30:29 +03:00
dev_info ( & d - > dev , " PIIX3: Enabling Passive Release \n " ) ;
2005-04-17 02:20:36 +04:00
dlc | = 1 < < 1 ;
pci_write_config_byte ( d , 0x82 , dlc ) ;
}
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82441 , quirk_passive_release ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82441 , quirk_passive_release ) ;
2005-04-17 02:20:36 +04:00
/* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
but VIA don ' t answer queries . If you happen to have good contacts at VIA
ask them for me please - - Alan
This appears to be BIOS not version dependent . So presumably there is a
chipset level fix */
static void __devinit quirk_isa_dma_hangs ( struct pci_dev * dev )
{
if ( ! isa_dma_bridge_buggy ) {
isa_dma_bridge_buggy = 1 ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Activating ISA DMA hang workarounds \n " ) ;
2005-04-17 02:20:36 +04:00
}
}
/*
* Its not totally clear which chipsets are the problematic ones
* We know 82 C586 and 82 C596 variants are affected .
*/
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C586_0 , quirk_isa_dma_hangs ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C596 , quirk_isa_dma_hangs ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82371SB_0 , quirk_isa_dma_hangs ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AL , PCI_DEVICE_ID_AL_M1533 , quirk_isa_dma_hangs ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_NEC , PCI_DEVICE_ID_NEC_CBUS_1 , quirk_isa_dma_hangs ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_NEC , PCI_DEVICE_ID_NEC_CBUS_2 , quirk_isa_dma_hangs ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_NEC , PCI_DEVICE_ID_NEC_CBUS_3 , quirk_isa_dma_hangs ) ;
2005-04-17 02:20:36 +04:00
/*
* Chipsets where PCI - > PCI transfers vanish or hang
*/
static void __devinit quirk_nopcipci ( struct pci_dev * dev )
{
if ( ( pci_pci_problems & PCIPCI_FAIL ) = = 0 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Disabling direct PCI/PCI transfers \n " ) ;
2005-04-17 02:20:36 +04:00
pci_pci_problems | = PCIPCI_FAIL ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_5597 , quirk_nopcipci ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_496 , quirk_nopcipci ) ;
2006-10-01 10:27:03 +04:00
static void __devinit quirk_nopciamd ( struct pci_dev * dev )
{
u8 rev ;
pci_read_config_byte ( dev , 0x08 , & rev ) ;
if ( rev = = 0x13 ) {
/* Erratum 24 */
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Chipset erratum: Disabling direct PCI/AGP transfers \n " ) ;
2006-10-01 10:27:03 +04:00
pci_pci_problems | = PCIAGP_FAIL ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8151_0 , quirk_nopciamd ) ;
2005-04-17 02:20:36 +04:00
/*
* Triton requires workarounds to be used by the drivers
*/
static void __devinit quirk_triton ( struct pci_dev * dev )
{
if ( ( pci_pci_problems & PCIPCI_TRITON ) = = 0 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Limiting direct PCI/PCI transfers \n " ) ;
2005-04-17 02:20:36 +04:00
pci_pci_problems | = PCIPCI_TRITON ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82437 , quirk_triton ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82437VX , quirk_triton ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82439 , quirk_triton ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82439TX , quirk_triton ) ;
2005-04-17 02:20:36 +04:00
/*
* VIA Apollo KT133 needs PCI latency patch
* Made according to a windows driver based patch by George E . Breese
* see PCI Latency Adjust on http : //www.viahardware.com/download/viatweak.shtm
* Also see http : //www.au-ja.org/review-kt133a-1-en.phtml for
* the info on which Mr Breese based his work .
*
* Updated based on further information from the site and also on
* information provided by VIA
*/
2006-12-05 02:14:45 +03:00
static void quirk_vialatency ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
struct pci_dev * p ;
u8 busarb ;
/* Ok we have a potential problem chipset here. Now see if we have
a buggy southbridge */
p = pci_get_device ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C686 , NULL ) ;
if ( p ! = NULL ) {
/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
/* Check for buggy part revisions */
2007-10-30 00:55:02 +03:00
if ( p - > revision < 0x40 | | p - > revision > 0x42 )
2005-04-17 02:20:36 +04:00
goto exit ;
} else {
p = pci_get_device ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8231 , NULL ) ;
if ( p = = NULL ) /* No problem parts */
goto exit ;
/* Check for buggy part revisions */
2007-10-30 00:55:02 +03:00
if ( p - > revision < 0x10 | | p - > revision > 0x12 )
2005-04-17 02:20:36 +04:00
goto exit ;
}
/*
* Ok we have the problem . Now set the PCI master grant to
* occur every master grant . The apparent bug is that under high
* PCI load ( quite common in Linux of course ) you can get data
* loss when the CPU is held off the bus for 3 bus master requests
* This happens to include the IDE controllers . . . .
*
* VIA only apply this fix when an SB Live ! is present but under
* both Linux and Windows this isnt enough , and we have seen
* corruption without SB Live ! but with things like 3 UDMA IDE
* controllers . So we ignore that bit of the VIA recommendation . .
*/
pci_read_config_byte ( dev , 0x76 , & busarb ) ;
/* Set bit 4 and bi 5 of byte 76 to 0x01
" Master priority rotation on every PCI master grant */
busarb & = ~ ( 1 < < 5 ) ;
busarb | = ( 1 < < 4 ) ;
pci_write_config_byte ( dev , 0x76 , busarb ) ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Applying VIA southbridge workaround \n " ) ;
2005-04-17 02:20:36 +04:00
exit :
pci_dev_put ( p ) ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8363_0 , quirk_vialatency ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8371_1 , quirk_vialatency ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8361 , quirk_vialatency ) ;
2006-12-05 02:14:45 +03:00
/* Must restore this on a resume from RAM */
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8363_0 , quirk_vialatency ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8371_1 , quirk_vialatency ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8361 , quirk_vialatency ) ;
2005-04-17 02:20:36 +04:00
/*
* VIA Apollo VP3 needs ETBF on BT848 / 878
*/
static void __devinit quirk_viaetbf ( struct pci_dev * dev )
{
if ( ( pci_pci_problems & PCIPCI_VIAETBF ) = = 0 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Limiting direct PCI/PCI transfers \n " ) ;
2005-04-17 02:20:36 +04:00
pci_pci_problems | = PCIPCI_VIAETBF ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C597_0 , quirk_viaetbf ) ;
2005-04-17 02:20:36 +04:00
static void __devinit quirk_vsfx ( struct pci_dev * dev )
{
if ( ( pci_pci_problems & PCIPCI_VSFX ) = = 0 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Limiting direct PCI/PCI transfers \n " ) ;
2005-04-17 02:20:36 +04:00
pci_pci_problems | = PCIPCI_VSFX ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C576 , quirk_vsfx ) ;
2005-04-17 02:20:36 +04:00
/*
* Ali Magik requires workarounds to be used by the drivers
* that DMA to AGP space . Latency must be set to 0xA and triton
* workaround applied too
* [ Info kindly provided by ALi ]
*/
static void __init quirk_alimagik ( struct pci_dev * dev )
{
if ( ( pci_pci_problems & PCIPCI_ALIMAGIK ) = = 0 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Limiting direct PCI/PCI transfers \n " ) ;
2005-04-17 02:20:36 +04:00
pci_pci_problems | = PCIPCI_ALIMAGIK | PCIPCI_TRITON ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AL , PCI_DEVICE_ID_AL_M1647 , quirk_alimagik ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AL , PCI_DEVICE_ID_AL_M1651 , quirk_alimagik ) ;
2005-04-17 02:20:36 +04:00
/*
* Natoma has some interesting boundary conditions with Zoran stuff
* at least
*/
static void __devinit quirk_natoma ( struct pci_dev * dev )
{
if ( ( pci_pci_problems & PCIPCI_NATOMA ) = = 0 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Limiting direct PCI/PCI transfers \n " ) ;
2005-04-17 02:20:36 +04:00
pci_pci_problems | = PCIPCI_NATOMA ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82441 , quirk_natoma ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82443LX_0 , quirk_natoma ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82443LX_1 , quirk_natoma ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82443BX_0 , quirk_natoma ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82443BX_1 , quirk_natoma ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82443BX_2 , quirk_natoma ) ;
2005-04-17 02:20:36 +04:00
/*
* This chip can cause PCI parity errors if config register 0xA0 is read
* while DMAs are occurring .
*/
static void __devinit quirk_citrine ( struct pci_dev * dev )
{
dev - > cfg_size = 0xA0 ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_IBM , PCI_DEVICE_ID_IBM_CITRINE , quirk_citrine ) ;
2005-04-17 02:20:36 +04:00
/*
* S3 868 and 968 chips report region size equal to 32 M , but they decode 64 M .
* If it ' s needed , re - allocate the region .
*/
static void __devinit quirk_s3_64M ( struct pci_dev * dev )
{
struct resource * r = & dev - > resource [ 0 ] ;
if ( ( r - > start & 0x3ffffff ) | | r - > end ! = r - > start + 0x3ffffff ) {
r - > start = 0 ;
r - > end = 0x3ffffff ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_S3 , PCI_DEVICE_ID_S3_868 , quirk_s3_64M ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_S3 , PCI_DEVICE_ID_S3_968 , quirk_s3_64M ) ;
2005-04-17 02:20:36 +04:00
2005-10-26 07:40:09 +04:00
static void __devinit quirk_io_region ( struct pci_dev * dev , unsigned region ,
unsigned size , int nr , const char * name )
2005-04-17 02:20:36 +04:00
{
region & = ~ ( size - 1 ) ;
if ( region ) {
2005-08-09 00:19:08 +04:00
struct pci_bus_region bus_region ;
2005-04-17 02:20:36 +04:00
struct resource * res = dev - > resource + nr ;
res - > name = pci_name ( dev ) ;
res - > start = region ;
res - > end = region + size - 1 ;
res - > flags = IORESOURCE_IO ;
2005-08-09 00:19:08 +04:00
/* Convert from PCI bus to resource space. */
bus_region . start = res - > start ;
bus_region . end = res - > end ;
pcibios_bus_to_resource ( dev , res , & bus_region ) ;
2005-04-17 02:20:36 +04:00
pci_claim_resource ( dev , nr ) ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " quirk: region %04x-%04x claimed by %s \n " , region , region + size - 1 , name ) ;
2005-04-17 02:20:36 +04:00
}
}
/*
* ATI Northbridge setups MCE the processor if you even
* read somewhere between 0x3b0 - > 0x3bb or read 0x3d3
*/
static void __devinit quirk_ati_exploding_mce ( struct pci_dev * dev )
{
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb \n " ) ;
2005-04-17 02:20:36 +04:00
/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
request_region ( 0x3b0 , 0x0C , " RadeonIGP " ) ;
request_region ( 0x3d3 , 0x01 , " RadeonIGP " ) ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_RS100 , quirk_ati_exploding_mce ) ;
2005-04-17 02:20:36 +04:00
/*
* Let ' s make the southbridge information explicit instead
* of having to worry about people probing the ACPI areas ,
* for example . . ( Yes , it happens , and if you read the wrong
* ACPI register it will put the machine to sleep with no
* way of waking it up again . Bummer ) .
*
* ALI M7101 : Two IO regions pointed to by words at
* 0xE0 ( 64 bytes of ACPI registers )
* 0xE2 ( 32 bytes of SMB registers )
*/
static void __devinit quirk_ali7101_acpi ( struct pci_dev * dev )
{
u16 region ;
pci_read_config_word ( dev , 0xE0 , & region ) ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , region , 64 , PCI_BRIDGE_RESOURCES , " ali7101 ACPI " ) ;
2005-04-17 02:20:36 +04:00
pci_read_config_word ( dev , 0xE2 , & region ) ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , region , 32 , PCI_BRIDGE_RESOURCES + 1 , " ali7101 SMB " ) ;
2005-04-17 02:20:36 +04:00
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_AL , PCI_DEVICE_ID_AL_M7101 , quirk_ali7101_acpi ) ;
2005-04-17 02:20:36 +04:00
2005-10-26 07:40:09 +04:00
static void piix4_io_quirk ( struct pci_dev * dev , const char * name , unsigned int port , unsigned int enable )
{
u32 devres ;
u32 mask , size , base ;
pci_read_config_dword ( dev , port , & devres ) ;
if ( ( devres & enable ) ! = enable )
return ;
mask = ( devres > > 16 ) & 15 ;
base = devres & 0xffff ;
size = 16 ;
for ( ; ; ) {
unsigned bit = size > > 1 ;
if ( ( bit & mask ) = = bit )
break ;
size = bit ;
}
/*
* For now we only print it out . Eventually we ' ll want to
* reserve it ( at least if it ' s in the 0x1000 + range ) , but
* let ' s get enough confirmation reports first .
*/
base & = - size ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " %s PIO at %04x-%04x \n " , name , base , base + size - 1 ) ;
2005-10-26 07:40:09 +04:00
}
static void piix4_mem_quirk ( struct pci_dev * dev , const char * name , unsigned int port , unsigned int enable )
{
u32 devres ;
u32 mask , size , base ;
pci_read_config_dword ( dev , port , & devres ) ;
if ( ( devres & enable ) ! = enable )
return ;
base = devres & 0xffff0000 ;
mask = ( devres & 0x3f ) < < 16 ;
size = 128 < < 16 ;
for ( ; ; ) {
unsigned bit = size > > 1 ;
if ( ( bit & mask ) = = bit )
break ;
size = bit ;
}
/*
* For now we only print it out . Eventually we ' ll want to
* reserve it , but let ' s get enough confirmation reports first .
*/
base & = - size ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " %s MMIO at %04x-%04x \n " , name , base , base + size - 1 ) ;
2005-10-26 07:40:09 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* PIIX4 ACPI : Two IO regions pointed to by longwords at
* 0x40 ( 64 bytes of ACPI registers )
2005-10-31 01:40:07 +03:00
* 0x90 ( 16 bytes of SMB registers )
2005-10-26 07:40:09 +04:00
* and a few strange programmable PIIX4 device resources .
2005-04-17 02:20:36 +04:00
*/
static void __devinit quirk_piix4_acpi ( struct pci_dev * dev )
{
2005-10-26 07:40:09 +04:00
u32 region , res_a ;
2005-04-17 02:20:36 +04:00
pci_read_config_dword ( dev , 0x40 , & region ) ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , region , 64 , PCI_BRIDGE_RESOURCES , " PIIX4 ACPI " ) ;
2005-04-17 02:20:36 +04:00
pci_read_config_dword ( dev , 0x90 , & region ) ;
2005-10-31 01:40:07 +03:00
quirk_io_region ( dev , region , 16 , PCI_BRIDGE_RESOURCES + 1 , " PIIX4 SMB " ) ;
2005-10-26 07:40:09 +04:00
/* Device resource A has enables for some of the other ones */
pci_read_config_dword ( dev , 0x5c , & res_a ) ;
piix4_io_quirk ( dev , " PIIX4 devres B " , 0x60 , 3 < < 21 ) ;
piix4_io_quirk ( dev , " PIIX4 devres C " , 0x64 , 3 < < 21 ) ;
/* Device resource D is just bitfields for static resources */
/* Device 12 enabled? */
if ( res_a & ( 1 < < 29 ) ) {
piix4_io_quirk ( dev , " PIIX4 devres E " , 0x68 , 1 < < 20 ) ;
piix4_mem_quirk ( dev , " PIIX4 devres F " , 0x6c , 1 < < 7 ) ;
}
/* Device 13 enabled? */
if ( res_a & ( 1 < < 30 ) ) {
piix4_io_quirk ( dev , " PIIX4 devres G " , 0x70 , 1 < < 20 ) ;
piix4_mem_quirk ( dev , " PIIX4 devres H " , 0x74 , 1 < < 7 ) ;
}
piix4_io_quirk ( dev , " PIIX4 devres I " , 0x78 , 1 < < 20 ) ;
piix4_io_quirk ( dev , " PIIX4 devres J " , 0x7c , 1 < < 20 ) ;
2005-04-17 02:20:36 +04:00
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82371AB_3 , quirk_piix4_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82443MX_3 , quirk_piix4_acpi ) ;
2005-04-17 02:20:36 +04:00
/*
* ICH4 , ICH4 - M , ICH5 , ICH5 - M ACPI : Three IO regions pointed to by longwords at
* 0x40 ( 128 bytes of ACPI , GPIO & TCO registers )
* 0x58 ( 64 bytes of GPIO I / O space )
*/
static void __devinit quirk_ich4_lpc_acpi ( struct pci_dev * dev )
{
u32 region ;
pci_read_config_dword ( dev , 0x40 , & region ) ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , region , 128 , PCI_BRIDGE_RESOURCES , " ICH4 ACPI/GPIO/TCO " ) ;
2005-04-17 02:20:36 +04:00
pci_read_config_dword ( dev , 0x58 , & region ) ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , region , 64 , PCI_BRIDGE_RESOURCES + 1 , " ICH4 GPIO " ) ;
2005-04-17 02:20:36 +04:00
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801AA_0 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801AB_0 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801BA_0 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801BA_10 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801CA_0 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801CA_12 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801DB_0 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801DB_12 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801EB_0 , quirk_ich4_lpc_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ESB_1 , quirk_ich4_lpc_acpi ) ;
2005-04-17 02:20:36 +04:00
2008-12-06 21:10:10 +03:00
static void __devinit ich6_lpc_acpi_gpio ( struct pci_dev * dev )
2005-09-28 01:54:51 +04:00
{
u32 region ;
pci_read_config_dword ( dev , 0x40 , & region ) ;
quirk_io_region ( dev , region , 128 , PCI_BRIDGE_RESOURCES , " ICH6 ACPI/GPIO/TCO " ) ;
pci_read_config_dword ( dev , 0x48 , & region ) ;
quirk_io_region ( dev , region , 64 , PCI_BRIDGE_RESOURCES + 1 , " ICH6 GPIO " ) ;
}
2008-12-06 21:10:10 +03:00
static void __devinit ich6_lpc_generic_decode ( struct pci_dev * dev , unsigned reg , const char * name , int dynsize )
{
u32 val ;
u32 size , base ;
pci_read_config_dword ( dev , reg , & val ) ;
/* Enabled? */
if ( ! ( val & 1 ) )
return ;
base = val & 0xfffc ;
if ( dynsize ) {
/*
* This is not correct . It is 16 , 32 or 64 bytes depending on
* register D31 : F0 : ADh bits 5 : 4.
*
* But this gets us at least _part_ of it .
*/
size = 16 ;
} else {
size = 128 ;
}
base & = ~ ( size - 1 ) ;
/* Just print it out for now. We should reserve it after more debugging */
dev_info ( & dev - > dev , " %s PIO at %04x-%04x \n " , name , base , base + size - 1 ) ;
}
static void __devinit quirk_ich6_lpc ( struct pci_dev * dev )
{
/* Shared ACPI/GPIO decode with all ICH6+ */
ich6_lpc_acpi_gpio ( dev ) ;
/* ICH6-specific generic IO decode */
ich6_lpc_generic_decode ( dev , 0x84 , " LPC Generic IO decode 1 " , 0 ) ;
ich6_lpc_generic_decode ( dev , 0x88 , " LPC Generic IO decode 2 " , 1 ) ;
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH6_0 , quirk_ich6_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH6_1 , quirk_ich6_lpc ) ;
static void __devinit ich7_lpc_generic_decode ( struct pci_dev * dev , unsigned reg , const char * name )
{
u32 val ;
u32 mask , base ;
pci_read_config_dword ( dev , reg , & val ) ;
/* Enabled? */
if ( ! ( val & 1 ) )
return ;
/*
* IO base in bits 15 : 2 , mask in bits 23 : 18 , both
* are dword - based
*/
base = val & 0xfffc ;
mask = ( val > > 16 ) & 0xfc ;
mask | = 3 ;
/* Just print it out for now. We should reserve it after more debugging */
dev_info ( & dev - > dev , " %s PIO at %04x (mask %04x) \n " , name , base , mask ) ;
}
/* ICH7-10 has the same common LPC generic IO decode registers */
static void __devinit quirk_ich7_lpc ( struct pci_dev * dev )
{
/* We share the common ACPI/DPIO decode with ICH6 */
ich6_lpc_acpi_gpio ( dev ) ;
/* And have 4 ICH7+ generic decodes */
ich7_lpc_generic_decode ( dev , 0x84 , " ICH7 LPC Generic IO decode 1 " ) ;
ich7_lpc_generic_decode ( dev , 0x88 , " ICH7 LPC Generic IO decode 2 " ) ;
ich7_lpc_generic_decode ( dev , 0x8c , " ICH7 LPC Generic IO decode 3 " ) ;
ich7_lpc_generic_decode ( dev , 0x90 , " ICH7 LPC Generic IO decode 4 " ) ;
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH7_0 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH7_1 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH7_31 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH8_0 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH8_2 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH8_3 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH8_1 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH8_4 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH9_2 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH9_4 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH9_7 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH9_8 , quirk_ich7_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH10_1 , quirk_ich7_lpc ) ;
2005-09-28 01:54:51 +04:00
2005-04-17 02:20:36 +04:00
/*
* VIA ACPI : One IO region pointed to by longword at
* 0x48 or 0x20 ( 256 bytes of ACPI registers )
*/
static void __devinit quirk_vt82c586_acpi ( struct pci_dev * dev )
{
u32 region ;
2007-08-28 03:18:10 +04:00
if ( dev - > revision & 0x10 ) {
2005-04-17 02:20:36 +04:00
pci_read_config_dword ( dev , 0x48 , & region ) ;
region & = PCI_BASE_ADDRESS_IO_MASK ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , region , 256 , PCI_BRIDGE_RESOURCES , " vt82c586 ACPI " ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C586_3 , quirk_vt82c586_acpi ) ;
2005-04-17 02:20:36 +04:00
/*
* VIA VT82C686 ACPI : Three IO region pointed to by ( long ) words at
* 0x48 ( 256 bytes of ACPI registers )
* 0x70 ( 128 bytes of hardware monitoring register )
* 0x90 ( 16 bytes of SMB registers )
*/
static void __devinit quirk_vt82c686_acpi ( struct pci_dev * dev )
{
u16 hm ;
u32 smb ;
quirk_vt82c586_acpi ( dev ) ;
pci_read_config_word ( dev , 0x70 , & hm ) ;
hm & = PCI_BASE_ADDRESS_IO_MASK ;
2005-10-29 14:31:49 +04:00
quirk_io_region ( dev , hm , 128 , PCI_BRIDGE_RESOURCES + 1 , " vt82c686 HW-mon " ) ;
2005-04-17 02:20:36 +04:00
pci_read_config_dword ( dev , 0x90 , & smb ) ;
smb & = PCI_BASE_ADDRESS_IO_MASK ;
2005-10-29 14:31:49 +04:00
quirk_io_region ( dev , smb , 16 , PCI_BRIDGE_RESOURCES + 2 , " vt82c686 SMB " ) ;
2005-04-17 02:20:36 +04:00
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C686_4 , quirk_vt82c686_acpi ) ;
2005-04-17 02:20:36 +04:00
2005-08-08 12:55:54 +04:00
/*
* VIA VT8235 ISA Bridge : Two IO regions pointed to by words at
* 0x88 ( 128 bytes of power management registers )
* 0xd0 ( 16 bytes of SMB registers )
*/
static void __devinit quirk_vt8235_acpi ( struct pci_dev * dev )
{
u16 pm , smb ;
pci_read_config_word ( dev , 0x88 , & pm ) ;
pm & = PCI_BASE_ADDRESS_IO_MASK ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , pm , 128 , PCI_BRIDGE_RESOURCES , " vt8235 PM " ) ;
2005-08-08 12:55:54 +04:00
pci_read_config_word ( dev , 0xd0 , & smb ) ;
smb & = PCI_BASE_ADDRESS_IO_MASK ;
2005-10-26 07:40:09 +04:00
quirk_io_region ( dev , smb , 16 , PCI_BRIDGE_RESOURCES + 1 , " vt8235 SMB " ) ;
2005-08-08 12:55:54 +04:00
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8235 , quirk_vt8235_acpi ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_X86_IO_APIC
# include <asm/io_apic.h>
/*
* VIA 686 A / B : If an IO - APIC is active , we need to route all on - chip
* devices to the external APIC .
*
* TODO : When we have device - specific interrupt routers ,
* this code will go away from quirks .
*/
2006-12-05 02:14:45 +03:00
static void quirk_via_ioapic ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
u8 tmp ;
if ( nr_ioapics < 1 )
tmp = 0 ; /* nothing routed to external APIC */
else
tmp = 0x1f ; /* all known bits (4-0) routed to external APIC */
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " %sbling VIA external APIC routing \n " ,
2005-04-17 02:20:36 +04:00
tmp = = 0 ? " Disa " : " Ena " ) ;
/* Offset 0x58: External APIC IRQ output control */
pci_write_config_byte ( dev , 0x58 , tmp ) ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C686 , quirk_via_ioapic ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C686 , quirk_via_ioapic ) ;
2005-04-17 02:20:36 +04:00
2005-09-04 02:56:33 +04:00
/*
* VIA 8237 : Some BIOSs don ' t set the ' Bypass APIC De - Assert Message ' Bit .
* This leads to doubled level interrupt rates .
* Set this bit to get rid of cycle wastage .
* Otherwise uncritical .
*/
2006-12-05 02:14:45 +03:00
static void quirk_via_vt8237_bypass_apic_deassert ( struct pci_dev * dev )
2005-09-04 02:56:33 +04:00
{
u8 misc_control2 ;
# define BYPASS_APIC_DEASSERT 8
pci_read_config_byte ( dev , 0x5B , & misc_control2 ) ;
if ( ! ( misc_control2 & BYPASS_APIC_DEASSERT ) ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Bypassing VIA 8237 APIC De-Assert Message \n " ) ;
2005-09-04 02:56:33 +04:00
pci_write_config_byte ( dev , 0x5B , misc_control2 | BYPASS_APIC_DEASSERT ) ;
}
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8237 , quirk_via_vt8237_bypass_apic_deassert ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8237 , quirk_via_vt8237_bypass_apic_deassert ) ;
2005-09-04 02:56:33 +04:00
2005-04-17 02:20:36 +04:00
/*
* The AMD io apic can hang the box when an apic irq is masked .
* We check all revs > = B0 ( yet not in the pre production ! ) as the bug
* is currently marked NoFix
*
* We have multiple reports of hangs with this chipset that went away with
2006-10-01 10:27:03 +04:00
* noapic specified . For the moment we assume it ' s the erratum . We may be wrong
2005-04-17 02:20:36 +04:00
* of course . However the advice is demonstrably good even if so . .
*/
static void __devinit quirk_amd_ioapic ( struct pci_dev * dev )
{
2007-06-09 02:46:36 +04:00
if ( dev - > revision > = 0x02 ) {
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " I/O APIC: AMD Erratum #22 may be present. In the event of instability try \n " ) ;
dev_warn ( & dev - > dev , " : booting with the \" noapic \" option \n " ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_VIPER_7410 , quirk_amd_ioapic ) ;
2005-04-17 02:20:36 +04:00
static void __init quirk_ioapic_rmw ( struct pci_dev * dev )
{
if ( dev - > devfn = = 0 & & dev - > bus - > number = = 0 )
sis_apic_bug = 1 ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_SI , PCI_ANY_ID , quirk_ioapic_rmw ) ;
2005-04-17 02:20:36 +04:00
# endif /* CONFIG_X86_IO_APIC */
2007-05-15 15:59:13 +04:00
/*
* Some settings of MMRBC can lead to data corruption so block changes .
* See AMD 8131 HyperTransport PCI - X Tunnel Revision Guide
*/
static void __init quirk_amd_8131_mmrbc ( struct pci_dev * dev )
{
2007-08-28 03:17:47 +04:00
if ( dev - > subordinate & & dev - > revision < = 0x12 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " AMD8131 rev %x detected; "
" disabling PCI-X MMRBC \n " , dev - > revision ) ;
2007-05-15 15:59:13 +04:00
dev - > subordinate - > bus_flags | = PCI_BUS_FLAGS_NO_MMRBC ;
}
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8131_BRIDGE , quirk_amd_8131_mmrbc ) ;
2005-04-17 02:20:36 +04:00
/*
* FIXME : it is questionable that quirk_via_acpi
* is needed . It shows up as an ISA bridge , and does not
* support the PCI_INTERRUPT_LINE register at all . Therefore
* it seems like setting the pci_dev ' s ' irq ' to the
* value of the ACPI SCI interrupt is only done for convenience .
* - jgarzik
*/
static void __devinit quirk_via_acpi ( struct pci_dev * d )
{
/*
* VIA ACPI device : SCI IRQ line in PCI config byte 0x42
*/
u8 irq ;
pci_read_config_byte ( d , 0x42 , & irq ) ;
irq & = 0xf ;
if ( irq & & ( irq ! = 2 ) )
d - > irq = irq ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C586_3 , quirk_via_acpi ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C686_4 , quirk_via_acpi ) ;
2005-04-17 02:20:36 +04:00
2006-09-26 03:52:19 +04:00
/*
2006-12-05 02:14:45 +03:00
* VIA bridges which have VLink
2006-09-26 03:52:19 +04:00
*/
2006-12-05 02:14:45 +03:00
2007-01-31 01:36:09 +03:00
static int via_vlink_dev_lo = - 1 , via_vlink_dev_hi = 18 ;
static void quirk_via_bridge ( struct pci_dev * dev )
{
/* See what bridge we have and find the device ranges */
switch ( dev - > device ) {
case PCI_DEVICE_ID_VIA_82C686 :
2007-02-01 10:48:12 +03:00
/* The VT82C686 is special, it attaches to PCI and can have
any device number . All its subdevices are functions of
that single device . */
via_vlink_dev_lo = PCI_SLOT ( dev - > devfn ) ;
via_vlink_dev_hi = PCI_SLOT ( dev - > devfn ) ;
2007-01-31 01:36:09 +03:00
break ;
case PCI_DEVICE_ID_VIA_8237 :
case PCI_DEVICE_ID_VIA_8237A :
via_vlink_dev_lo = 15 ;
break ;
case PCI_DEVICE_ID_VIA_8235 :
via_vlink_dev_lo = 16 ;
break ;
case PCI_DEVICE_ID_VIA_8231 :
case PCI_DEVICE_ID_VIA_8233_0 :
case PCI_DEVICE_ID_VIA_8233A :
case PCI_DEVICE_ID_VIA_8233C_0 :
via_vlink_dev_lo = 17 ;
break ;
}
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C686 , quirk_via_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8231 , quirk_via_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8233_0 , quirk_via_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8233A , quirk_via_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8233C_0 , quirk_via_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8235 , quirk_via_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8237 , quirk_via_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8237A , quirk_via_bridge ) ;
2006-09-26 03:52:19 +04:00
2006-12-05 02:14:45 +03:00
/**
* quirk_via_vlink - VIA VLink IRQ number update
* @ dev : PCI device
*
* If the device we are dealing with is on a PIC IRQ we need to
* ensure that the IRQ line register which usually is not relevant
* for PCI cards , is actually written so that interrupts get sent
2007-01-31 01:36:09 +03:00
* to the right place .
* We only do this on systems where a VIA south bridge was detected ,
* and only for VIA devices on the motherboard ( see quirk_via_bridge
* above ) .
2006-12-05 02:14:45 +03:00
*/
static void quirk_via_vlink ( struct pci_dev * dev )
2005-05-27 12:21:50 +04:00
{
u8 irq , new_irq ;
2007-01-31 01:36:09 +03:00
/* Check if we have VLink at all */
if ( via_vlink_dev_lo = = - 1 )
2006-09-26 03:52:19 +04:00
return ;
new_irq = dev - > irq ;
/* Don't quirk interrupts outside the legacy IRQ range */
if ( ! new_irq | | new_irq > 15 )
return ;
2006-12-05 02:14:45 +03:00
/* Internal device ? */
2007-01-31 01:36:09 +03:00
if ( dev - > bus - > number ! = 0 | | PCI_SLOT ( dev - > devfn ) > via_vlink_dev_hi | |
PCI_SLOT ( dev - > devfn ) < via_vlink_dev_lo )
2006-12-05 02:14:45 +03:00
return ;
/* This is an internal VLink device on a PIC interrupt. The BIOS
ought to have set this but may not have , so we redo it */
2005-05-27 12:21:50 +04:00
pci_read_config_byte ( dev , PCI_INTERRUPT_LINE , & irq ) ;
if ( new_irq ! = irq ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " VIA VLink IRQ fixup, from %d to %d \n " ,
irq , new_irq ) ;
2005-05-27 12:21:50 +04:00
udelay ( 15 ) ; /* unknown if delay really needed */
pci_write_config_byte ( dev , PCI_INTERRUPT_LINE , new_irq ) ;
}
}
2006-12-05 02:14:45 +03:00
DECLARE_PCI_FIXUP_ENABLE ( PCI_VENDOR_ID_VIA , PCI_ANY_ID , quirk_via_vlink ) ;
2005-05-27 12:21:50 +04:00
2005-04-17 02:20:36 +04:00
/*
* VIA VT82C598 has its device ID settable and many BIOSes
* set it to the ID of VT82C597 for backward compatibility .
* We need to switch it off to be able to recognize the real
* type of the chip .
*/
static void __devinit quirk_vt82c598_id ( struct pci_dev * dev )
{
pci_write_config_byte ( dev , 0xfc , 0 ) ;
pci_read_config_word ( dev , PCI_DEVICE_ID , & dev - > device ) ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_82C597_0 , quirk_vt82c598_id ) ;
2005-04-17 02:20:36 +04:00
/*
* CardBus controllers have a legacy base address that enables them
* to respond as i82365 pcmcia controllers . We don ' t want them to
* do this even if the Linux CardBus driver is not loaded , because
* the Linux i82365 driver does not ( and should not ) handle CardBus .
*/
2006-12-05 02:14:45 +03:00
static void quirk_cardbus_legacy ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
if ( ( PCI_CLASS_BRIDGE_CARDBUS < < 8 ) ^ dev - > class )
return ;
pci_write_config_dword ( dev , PCI_CB_LEGACY_MODE_BASE , 0 ) ;
}
DECLARE_PCI_FIXUP_FINAL ( PCI_ANY_ID , PCI_ANY_ID , quirk_cardbus_legacy ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_ANY_ID , PCI_ANY_ID , quirk_cardbus_legacy ) ;
2005-04-17 02:20:36 +04:00
/*
* Following the PCI ordering rules is optional on the AMD762 . I ' m not
* sure what the designers were smoking but let ' s not inhale . . .
*
* To be fair to AMD , it follows the spec by default , its BIOS people
* who turn it off !
*/
2006-12-05 02:14:45 +03:00
static void quirk_amd_ordering ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
u32 pcic ;
pci_read_config_dword ( dev , 0x4C , & pcic ) ;
if ( ( pcic & 6 ) ! = 6 ) {
pcic | = 6 ;
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " BIOS failed to enable PCI standards compliance; fixing this error \n " ) ;
2005-04-17 02:20:36 +04:00
pci_write_config_dword ( dev , 0x4C , pcic ) ;
pci_read_config_dword ( dev , 0x84 , & pcic ) ;
pcic | = ( 1 < < 23 ) ; /* Required in this mode */
pci_write_config_dword ( dev , 0x84 , pcic ) ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_FE_GATE_700C , quirk_amd_ordering ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_FE_GATE_700C , quirk_amd_ordering ) ;
2005-04-17 02:20:36 +04:00
/*
* DreamWorks provided workaround for Dunord I - 3000 problem
*
* This card decodes and responds to addresses not apparently
* assigned to it . We force a larger allocation to ensure that
* nothing gets put too close to it .
*/
static void __devinit quirk_dunord ( struct pci_dev * dev )
{
struct resource * r = & dev - > resource [ 1 ] ;
r - > start = 0 ;
r - > end = 0xffffff ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_DUNORD , PCI_DEVICE_ID_DUNORD_I3000 , quirk_dunord ) ;
2005-04-17 02:20:36 +04:00
/*
* i82380FB mobile docking controller : its PCI - to - PCI bridge
* is subtractive decoding ( transparent ) , and does indicate this
* in the ProgIf . Unfortunately , the ProgIf value is wrong - 0x80
* instead of 0x01 .
*/
static void __devinit quirk_transparent_bridge ( struct pci_dev * dev )
{
dev - > transparent = 1 ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82380FB , quirk_transparent_bridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_TOSHIBA , 0x605 , quirk_transparent_bridge ) ;
2005-04-17 02:20:36 +04:00
/*
* Common misconfiguration of the MediaGX / Geode PCI master that will
* reduce PCI bandwidth from 70 MB / s to 25 MB / s . See the GXM / GXLV / GX1
* datasheets found at http : //www.national.com/ds/GX for info on what
* these bits do . < christer @ weinigel . se >
*/
2006-12-05 02:14:45 +03:00
static void quirk_mediagx_master ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
u8 reg ;
pci_read_config_byte ( dev , 0x41 , & reg ) ;
if ( reg & 2 ) {
reg & = ~ 2 ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x) \n " , reg ) ;
2005-04-17 02:20:36 +04:00
pci_write_config_byte ( dev , 0x41 , reg ) ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_CYRIX , PCI_DEVICE_ID_CYRIX_PCI_MASTER , quirk_mediagx_master ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_CYRIX , PCI_DEVICE_ID_CYRIX_PCI_MASTER , quirk_mediagx_master ) ;
2005-04-17 02:20:36 +04:00
/*
* Ensure C0 rev restreaming is off . This is normally done by
* the BIOS but in the odd case it is not the results are corruption
* hence the presence of a Linux check
*/
2006-12-05 02:14:45 +03:00
static void quirk_disable_pxb ( struct pci_dev * pdev )
2005-04-17 02:20:36 +04:00
{
u16 config ;
2007-06-09 02:46:36 +04:00
if ( pdev - > revision ! = 0x04 ) /* Only C0 requires this */
2005-04-17 02:20:36 +04:00
return ;
pci_read_config_word ( pdev , 0x40 , & config ) ;
if ( config & ( 1 < < 6 ) ) {
config & = ~ ( 1 < < 6 ) ;
pci_write_config_word ( pdev , 0x40 , config ) ;
2007-12-18 00:09:39 +03:00
dev_info ( & pdev - > dev , " C0 revision 450NX. Disabling PCI restreaming \n " ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82454NX , quirk_disable_pxb ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82454NX , quirk_disable_pxb ) ;
2005-04-17 02:20:36 +04:00
2008-02-02 08:56:56 +03:00
static void __devinit quirk_amd_ide_mode ( struct pci_dev * pdev )
2006-12-20 00:11:37 +03:00
{
2008-02-02 08:56:56 +03:00
/* set sb600/sb700/sb800 sata to ahci mode */
u8 tmp ;
2006-12-20 00:11:37 +03:00
2008-02-02 08:56:56 +03:00
pci_read_config_byte ( pdev , PCI_CLASS_DEVICE , & tmp ) ;
if ( tmp = = 0x01 ) {
2006-12-20 00:11:37 +03:00
pci_read_config_byte ( pdev , 0x40 , & tmp ) ;
pci_write_config_byte ( pdev , 0x40 , tmp | 1 ) ;
pci_write_config_byte ( pdev , 0x9 , 1 ) ;
pci_write_config_byte ( pdev , 0xa , 6 ) ;
pci_write_config_byte ( pdev , 0x40 , tmp ) ;
2007-01-09 13:32:51 +03:00
pdev - > class = PCI_CLASS_STORAGE_SATA_AHCI ;
2008-02-02 08:56:56 +03:00
dev_info ( & pdev - > dev , " set SATA to AHCI mode \n " ) ;
2006-12-20 00:11:37 +03:00
}
}
2008-02-02 08:56:56 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_IXP600_SATA , quirk_amd_ide_mode ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_IXP600_SATA , quirk_amd_ide_mode ) ;
2008-02-02 08:56:56 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_IXP700_SATA , quirk_amd_ide_mode ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_IXP700_SATA , quirk_amd_ide_mode ) ;
2006-12-20 00:11:37 +03:00
2005-04-17 02:20:36 +04:00
/*
* Serverworks CSB5 IDE does not fully support native mode
*/
static void __devinit quirk_svwks_csb5ide ( struct pci_dev * pdev )
{
u8 prog ;
pci_read_config_byte ( pdev , PCI_CLASS_PROG , & prog ) ;
if ( prog & 5 ) {
prog & = ~ 5 ;
pdev - > class & = ~ 5 ;
pci_write_config_byte ( pdev , PCI_CLASS_PROG , prog ) ;
2006-10-04 03:41:26 +04:00
/* PCI layer will sort out resources */
2005-04-17 02:20:36 +04:00
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_SERVERWORKS , PCI_DEVICE_ID_SERVERWORKS_CSB5IDE , quirk_svwks_csb5ide ) ;
2005-04-17 02:20:36 +04:00
/*
* Intel 82801 CAM ICH3 - M datasheet says IDE modes must be the same
*/
static void __init quirk_ide_samemode ( struct pci_dev * pdev )
{
u8 prog ;
pci_read_config_byte ( pdev , PCI_CLASS_PROG , & prog ) ;
if ( ( ( prog & 1 ) & & ! ( prog & 4 ) ) | | ( ( prog & 4 ) & & ! ( prog & 1 ) ) ) {
2007-12-18 00:09:39 +03:00
dev_info ( & pdev - > dev , " IDE mode mismatch; forcing legacy mode \n " ) ;
2005-04-17 02:20:36 +04:00
prog & = ~ 5 ;
pdev - > class & = ~ 5 ;
pci_write_config_byte ( pdev , PCI_CLASS_PROG , prog ) ;
}
}
2006-10-04 03:41:26 +04:00
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801CA_10 , quirk_ide_samemode ) ;
2005-04-17 02:20:36 +04:00
2008-07-24 20:18:38 +04:00
/*
* Some ATA devices break if put into D3
*/
static void __devinit quirk_no_ata_d3 ( struct pci_dev * pdev )
{
/* Quirk the legacy ATA devices only. The AHCI ones are ok */
if ( ( pdev - > class > > 8 ) = = PCI_CLASS_STORAGE_IDE )
pdev - > dev_flags | = PCI_DEV_FLAGS_NO_D3 ;
}
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_SERVERWORKS , PCI_ANY_ID , quirk_no_ata_d3 ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_ATI , PCI_ANY_ID , quirk_no_ata_d3 ) ;
2009-06-24 19:02:27 +04:00
/* ALi loses some register settings that we cannot then restore */
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_AL , PCI_ANY_ID , quirk_no_ata_d3 ) ;
/* VIA comes back fine but we need to keep it alive or ACPI GTM failures
occur when mode detecting */
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_VIA , PCI_ANY_ID , quirk_no_ata_d3 ) ;
2008-07-24 20:18:38 +04:00
2005-04-17 02:20:36 +04:00
/* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI / EISA bridge appears as non - classified . Fix that .
*/
static void __init quirk_eisa_bridge ( struct pci_dev * dev )
{
dev - > class = PCI_CLASS_BRIDGE_EISA < < 8 ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82375 , quirk_eisa_bridge ) ;
2005-04-17 02:20:36 +04:00
2006-04-20 13:43:17 +04:00
2005-04-17 02:20:36 +04:00
/*
* On ASUS P4B boards , the SMBus PCI Device within the ICH2 / 4 southbridge
* is not activated . The myth is that Asus said that they do not want the
* users to be irritated by just another PCI Device in the Win98 device
* manager . ( see the file prog / hotplug / README . p4b in the lm_sensors
* package 2.7 .0 for details )
*
* The SMBus PCI Device can be activated by setting a bit in the ICH LPC
* bridge . Unfortunately , this device has no subvendor / subdevice ID . So it
2007-08-23 23:22:04 +04:00
* becomes necessary to do this tweak in two steps - - the chosen trigger
* is either the Host bridge ( preferred ) or on - board VGA controller .
2007-03-24 18:56:44 +03:00
*
* Note that we used to unhide the SMBus that way on Toshiba laptops
* ( Satellite A40 and Tecra M2 ) but then found that the thermal management
* was done by SMM code , which could cause unsynchronized concurrent
* accesses to the SMBus registers , with potentially bad effects . Thus you
* should be very careful when adding new entries : if SMM is accessing the
* Intel SMBus , this is a very good reason to leave it hidden .
2008-03-29 00:16:04 +03:00
*
* Likewise , many recent laptops use ACPI for thermal management . If the
* ACPI DSDT code accesses the SMBus , then Linux should not access it
* natively , and keeping the SMBus hidden is the right thing to do . If you
* are about to add an entry in the table below , please first disassemble
* the DSDT and double - check that there is no code accessing the SMBus .
2005-04-17 02:20:36 +04:00
*/
2007-01-11 03:52:44 +03:00
static int asus_hides_smbus ;
2005-04-17 02:20:36 +04:00
static void __init asus_hides_smbus_hostbridge ( struct pci_dev * dev )
{
if ( unlikely ( dev - > subsystem_vendor = = PCI_VENDOR_ID_ASUSTEK ) ) {
if ( dev - > device = = PCI_DEVICE_ID_INTEL_82845_HB )
switch ( dev - > subsystem_device ) {
2005-06-29 19:04:06 +04:00
case 0x8025 : /* P4B-LX */
2005-04-17 02:20:36 +04:00
case 0x8070 : /* P4B */
case 0x8088 : /* P4B533 */
case 0x1626 : /* L3C notebook */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82845G_HB )
2005-04-17 02:20:36 +04:00
switch ( dev - > subsystem_device ) {
case 0x80b1 : /* P4GE-V */
case 0x80b2 : /* P4PE */
case 0x8093 : /* P4B533-V */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82850_HB )
2005-04-17 02:20:36 +04:00
switch ( dev - > subsystem_device ) {
case 0x8030 : /* P4T533 */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_7205_0 )
2005-04-17 02:20:36 +04:00
switch ( dev - > subsystem_device ) {
case 0x8070 : /* P4G8X Deluxe */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_E7501_MCH )
2006-07-31 10:53:15 +04:00
switch ( dev - > subsystem_device ) {
case 0x80c9 : /* PU-DLS */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82855GM_HB )
2005-04-17 02:20:36 +04:00
switch ( dev - > subsystem_device ) {
case 0x1751 : /* M2N notebook */
case 0x1821 : /* M5N notebook */
2009-05-12 14:05:23 +04:00
case 0x1897 : /* A6L notebook */
2005-04-17 02:20:36 +04:00
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82855PM_HB )
2005-04-17 02:20:36 +04:00
switch ( dev - > subsystem_device ) {
case 0x184b : /* W1N notebook */
case 0x186a : /* M6Ne notebook */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82865_HB )
2007-01-05 11:17:56 +03:00
switch ( dev - > subsystem_device ) {
case 0x80f2 : /* P4P800-X */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82915GM_HB )
2005-09-29 12:35:41 +04:00
switch ( dev - > subsystem_device ) {
case 0x1882 : /* M6V notebook */
2006-04-01 18:46:35 +04:00
case 0x1977 : /* A6VA notebook */
2005-09-29 12:35:41 +04:00
asus_hides_smbus = 1 ;
}
2005-04-17 02:20:36 +04:00
} else if ( unlikely ( dev - > subsystem_vendor = = PCI_VENDOR_ID_HP ) ) {
if ( dev - > device = = PCI_DEVICE_ID_INTEL_82855PM_HB )
switch ( dev - > subsystem_device ) {
case 0x088C : /* HP Compaq nc8000 */
case 0x0890 : /* HP Compaq nc6000 */
asus_hides_smbus = 1 ;
}
2007-01-05 13:23:15 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82865_HB )
2005-04-17 02:20:36 +04:00
switch ( dev - > subsystem_device ) {
case 0x12bc : /* HP D330L */
2005-09-22 00:26:31 +04:00
case 0x12bd : /* HP D530 */
2009-05-13 00:49:25 +04:00
case 0x006a : /* HP Compaq nx9500 */
2005-04-17 02:20:36 +04:00
asus_hides_smbus = 1 ;
}
2007-11-21 20:29:06 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82875_HB )
switch ( dev - > subsystem_device ) {
case 0x12bf : /* HP xw4100 */
asus_hides_smbus = 1 ;
}
2005-04-17 02:20:36 +04:00
} else if ( unlikely ( dev - > subsystem_vendor = = PCI_VENDOR_ID_SAMSUNG ) ) {
if ( dev - > device = = PCI_DEVICE_ID_INTEL_82855PM_HB )
switch ( dev - > subsystem_device ) {
case 0xC00C : /* Samsung P35 notebook */
asus_hides_smbus = 1 ;
}
2005-09-07 00:39:32 +04:00
} else if ( unlikely ( dev - > subsystem_vendor = = PCI_VENDOR_ID_COMPAQ ) ) {
if ( dev - > device = = PCI_DEVICE_ID_INTEL_82855PM_HB )
switch ( dev - > subsystem_device ) {
case 0x0058 : /* Compaq Evo N620c */
asus_hides_smbus = 1 ;
}
2007-08-23 23:22:04 +04:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82810_IG3 )
switch ( dev - > subsystem_device ) {
case 0xB16C : /* Compaq Deskpro EP 401963-001 (PCA# 010174) */
/* Motherboard doesn't have Host bridge
* subvendor / subdevice IDs , therefore checking
* its on - board VGA controller */
asus_hides_smbus = 1 ;
}
2009-03-02 11:51:13 +03:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82801DB_2 )
2008-06-04 15:53:31 +04:00
switch ( dev - > subsystem_device ) {
case 0x00b8 : /* Compaq Evo D510 CMT */
case 0x00b9 : /* Compaq Evo D510 SFF */
2009-03-02 11:51:13 +03:00
/* Motherboard doesn't have Host bridge
* subvendor / subdevice IDs and on - board VGA
* controller is disabled if an AGP card is
* inserted , therefore checking USB UHCI
* Controller # 1 */
2008-06-04 15:53:31 +04:00
asus_hides_smbus = 1 ;
}
2008-06-08 15:47:02 +04:00
else if ( dev - > device = = PCI_DEVICE_ID_INTEL_82815_CGC )
switch ( dev - > subsystem_device ) {
case 0x001A : /* Compaq Deskpro EN SSF P667 815E */
/* Motherboard doesn't have host bridge
* subvendor / subdevice IDs , therefore checking
* its on - board VGA controller */
asus_hides_smbus = 1 ;
}
2005-04-17 02:20:36 +04:00
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82845_HB , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82845G_HB , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82850_HB , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82865_HB , asus_hides_smbus_hostbridge ) ;
2007-11-21 20:29:06 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82875_HB , asus_hides_smbus_hostbridge ) ;
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_7205_0 , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_E7501_MCH , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82855PM_HB , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82855GM_HB , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82915GM_HB , asus_hides_smbus_hostbridge ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82810_IG3 , asus_hides_smbus_hostbridge ) ;
2009-03-02 11:51:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801DB_2 , asus_hides_smbus_hostbridge ) ;
2008-06-08 15:47:02 +04:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82815_CGC , asus_hides_smbus_hostbridge ) ;
2007-08-23 23:22:04 +04:00
2006-12-05 02:14:45 +03:00
static void asus_hides_smbus_lpc ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
u16 val ;
if ( likely ( ! asus_hides_smbus ) )
return ;
pci_read_config_word ( dev , 0xF2 , & val ) ;
if ( val & 0x8 ) {
pci_write_config_word ( dev , 0xF2 , val & ( ~ 0x8 ) ) ;
pci_read_config_word ( dev , 0xF2 , & val ) ;
if ( val & 0x8 )
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " i801 SMBus device continues to play 'hide and seek'! 0x%x \n " , val ) ;
2005-04-17 02:20:36 +04:00
else
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Enabled i801 SMBus device \n " ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801AA_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801DB_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801BA_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801CA_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801CA_12 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801DB_12 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801EB_0 , asus_hides_smbus_lpc ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801AA_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801DB_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801BA_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801CA_0 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801CA_12 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801DB_12 , asus_hides_smbus_lpc ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82801EB_0 , asus_hides_smbus_lpc ) ;
2006-12-05 02:14:45 +03:00
2008-05-15 23:51:31 +04:00
/* It appears we just have one such device. If not, we have a warning */
static void __iomem * asus_rcba_base ;
static void asus_hides_smbus_lpc_ich6_suspend ( struct pci_dev * dev )
2005-09-29 12:35:41 +04:00
{
2008-05-15 23:51:31 +04:00
u32 rcba ;
2005-09-29 12:35:41 +04:00
if ( likely ( ! asus_hides_smbus ) )
return ;
2008-05-15 23:51:31 +04:00
WARN_ON ( asus_rcba_base ) ;
2005-09-29 12:35:41 +04:00
pci_read_config_dword ( dev , 0xF0 , & rcba ) ;
2008-05-15 23:51:31 +04:00
/* use bits 31:14, 16 kB aligned */
asus_rcba_base = ioremap_nocache ( rcba & 0xFFFFC000 , 0x4000 ) ;
if ( asus_rcba_base = = NULL )
return ;
}
static void asus_hides_smbus_lpc_ich6_resume_early ( struct pci_dev * dev )
{
u32 val ;
if ( likely ( ! asus_hides_smbus | | ! asus_rcba_base ) )
return ;
/* read the Function Disable register, dword mode only */
val = readl ( asus_rcba_base + 0x3418 ) ;
writel ( val & 0xFFFFFFF7 , asus_rcba_base + 0x3418 ) ; /* enable the SMBus device */
}
static void asus_hides_smbus_lpc_ich6_resume ( struct pci_dev * dev )
{
if ( likely ( ! asus_hides_smbus | | ! asus_rcba_base ) )
return ;
iounmap ( asus_rcba_base ) ;
asus_rcba_base = NULL ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Enabled ICH6/i801 SMBus device \n " ) ;
2005-09-29 12:35:41 +04:00
}
2008-05-15 23:51:31 +04:00
static void asus_hides_smbus_lpc_ich6 ( struct pci_dev * dev )
{
asus_hides_smbus_lpc_ich6_suspend ( dev ) ;
asus_hides_smbus_lpc_ich6_resume_early ( dev ) ;
asus_hides_smbus_lpc_ich6_resume ( dev ) ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH6_1 , asus_hides_smbus_lpc_ich6 ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_SUSPEND ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH6_1 , asus_hides_smbus_lpc_ich6_suspend ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH6_1 , asus_hides_smbus_lpc_ich6_resume ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ICH6_1 , asus_hides_smbus_lpc_ich6_resume_early ) ;
2006-05-15 20:44:33 +04:00
2005-04-17 02:20:36 +04:00
/*
* SiS 96 x south bridge : BIOS typically hides SMBus device . . .
*/
2006-12-05 02:14:45 +03:00
static void quirk_sis_96x_smbus ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
u8 val = 0 ;
pci_read_config_byte ( dev , 0x77 , & val ) ;
2007-01-09 06:11:29 +03:00
if ( val & 0x10 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Enabling SiS 96x SMBus \n " ) ;
2007-01-09 06:11:29 +03:00
pci_write_config_byte ( dev , 0x77 , val & ~ 0x10 ) ;
}
2005-04-17 02:20:36 +04:00
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_961 , quirk_sis_96x_smbus ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_962 , quirk_sis_96x_smbus ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_963 , quirk_sis_96x_smbus ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_LPC , quirk_sis_96x_smbus ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_961 , quirk_sis_96x_smbus ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_962 , quirk_sis_96x_smbus ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_963 , quirk_sis_96x_smbus ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_LPC , quirk_sis_96x_smbus ) ;
2005-04-17 02:20:36 +04:00
/*
* . . . This is further complicated by the fact that some SiS96x south
* bridges pretend to be 85 C503 / 5513 instead . In that case see if we
* spotted a compatible north bridge to make sure .
* ( pci_find_device doesn ' t work yet )
*
* We can also enable the sis96x bit in the discovery register . .
*/
# define SIS_DETECT_REGISTER 0x40
2006-12-05 02:14:45 +03:00
static void quirk_sis_503 ( struct pci_dev * dev )
2005-04-17 02:20:36 +04:00
{
u8 reg ;
u16 devid ;
pci_read_config_byte ( dev , SIS_DETECT_REGISTER , & reg ) ;
pci_write_config_byte ( dev , SIS_DETECT_REGISTER , reg | ( 1 < < 6 ) ) ;
pci_read_config_word ( dev , PCI_DEVICE_ID , & devid ) ;
if ( ( ( devid & 0xfff0 ) ! = 0x0960 ) & & ( devid ! = 0x0018 ) ) {
pci_write_config_byte ( dev , SIS_DETECT_REGISTER , reg ) ;
return ;
}
/*
2007-01-09 06:11:29 +03:00
* Ok , it now shows up as a 96 x . . run the 96 x quirk by
* hand in case it has already been processed .
* ( depends on link order , which is apparently not guaranteed )
2005-04-17 02:20:36 +04:00
*/
dev - > device = devid ;
2007-01-09 06:11:29 +03:00
quirk_sis_96x_smbus ( dev ) ;
2005-04-17 02:20:36 +04:00
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_503 , quirk_sis_503 ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_SI , PCI_DEVICE_ID_SI_503 , quirk_sis_503 ) ;
2005-04-17 02:20:36 +04:00
2006-02-28 23:44:36 +03:00
/*
* On ASUS A8V and A8V Deluxe boards , the onboard AC97 audio controller
* and MC97 modem controller are disabled when a second PCI soundcard is
* present . This patch , tweaking the VT8237 ISA bridge , enables them .
* - - bjd
*/
2006-12-05 02:14:45 +03:00
static void asus_hides_ac97_lpc ( struct pci_dev * dev )
2006-02-28 23:44:36 +03:00
{
u8 val ;
int asus_hides_ac97 = 0 ;
if ( likely ( dev - > subsystem_vendor = = PCI_VENDOR_ID_ASUSTEK ) ) {
if ( dev - > device = = PCI_DEVICE_ID_VIA_8237 )
asus_hides_ac97 = 1 ;
}
if ( ! asus_hides_ac97 )
return ;
pci_read_config_byte ( dev , 0x50 , & val ) ;
if ( val & 0xc0 ) {
pci_write_config_byte ( dev , 0x50 , val & ( ~ 0xc0 ) ) ;
pci_read_config_byte ( dev , 0x50 , & val ) ;
if ( val & 0xc0 )
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x \n " , val ) ;
2006-02-28 23:44:36 +03:00
else
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Enabled onboard AC97/MC97 devices \n " ) ;
2006-02-28 23:44:36 +03:00
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8237 , asus_hides_ac97_lpc ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_8237 , asus_hides_ac97_lpc ) ;
2006-12-05 02:14:45 +03:00
2006-08-18 22:54:39 +04:00
# if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)
2006-07-12 18:05:41 +04:00
/*
* If we are using libata we can drive this chip properly but must
* do this early on to make the additional device appear during
* the PCI scanning .
*/
2007-02-26 14:16:13 +03:00
static void quirk_jmicron_ata ( struct pci_dev * pdev )
2006-07-12 18:05:41 +04:00
{
2007-02-26 14:24:03 +03:00
u32 conf1 , conf5 , class ;
2006-07-12 18:05:41 +04:00
u8 hdr ;
/* Only poke fn 0 */
if ( PCI_FUNC ( pdev - > devfn ) )
return ;
2007-02-26 14:16:13 +03:00
pci_read_config_dword ( pdev , 0x40 , & conf1 ) ;
pci_read_config_dword ( pdev , 0x80 , & conf5 ) ;
2006-07-12 18:05:41 +04:00
2007-02-26 14:16:13 +03:00
conf1 & = ~ 0x00CFF302 ; /* Clear bit 1, 8, 9, 12-19, 22, 23 */
conf5 & = ~ ( 1 < < 24 ) ; /* Clear bit 24 */
switch ( pdev - > device ) {
case PCI_DEVICE_ID_JMICRON_JMB360 :
/* The controller should be in single function ahci mode */
conf1 | = 0x0002A100 ; /* Set 8, 13, 15, 17 */
break ;
case PCI_DEVICE_ID_JMICRON_JMB365 :
case PCI_DEVICE_ID_JMICRON_JMB366 :
/* Redirect IDE second PATA port to the right spot */
conf5 | = ( 1 < < 24 ) ;
/* Fall through */
case PCI_DEVICE_ID_JMICRON_JMB361 :
case PCI_DEVICE_ID_JMICRON_JMB363 :
/* Enable dual function mode, AHCI on fn 0, IDE fn1 */
/* Set the class codes correctly and then direct IDE 0 */
2007-10-23 10:27:31 +04:00
conf1 | = 0x00C2A1B3 ; /* Set 0, 1, 4, 5, 7, 8, 13, 15, 17, 22, 23 */
2007-02-26 14:16:13 +03:00
break ;
case PCI_DEVICE_ID_JMICRON_JMB368 :
/* The controller should be in single function IDE mode */
conf1 | = 0x00C00000 ; /* Set 22, 23 */
break ;
2006-07-12 18:05:41 +04:00
}
2007-02-26 14:16:13 +03:00
pci_write_config_dword ( pdev , 0x40 , conf1 ) ;
pci_write_config_dword ( pdev , 0x80 , conf5 ) ;
/* Update pdev accordingly */
pci_read_config_byte ( pdev , PCI_HEADER_TYPE , & hdr ) ;
pdev - > hdr_type = hdr & 0x7f ;
pdev - > multifunction = ! ! ( hdr & 0x80 ) ;
2007-02-26 14:24:03 +03:00
pci_read_config_dword ( pdev , PCI_CLASS_REVISION , & class ) ;
pdev - > class = class > > 8 ;
2006-07-12 18:05:41 +04:00
}
2007-02-26 14:16:13 +03:00
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB360 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB361 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB363 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB365 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB366 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB368 , quirk_jmicron_ata ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB360 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB361 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB363 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB365 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB366 , quirk_jmicron_ata ) ;
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_JMICRON , PCI_DEVICE_ID_JMICRON_JMB368 , quirk_jmicron_ata ) ;
2006-07-12 18:05:41 +04:00
# endif
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_X86_IO_APIC
static void __init quirk_alder_ioapic ( struct pci_dev * pdev )
{
int i ;
if ( ( pdev - > class > > 8 ) ! = 0xff00 )
return ;
/* the first BAR is the location of the IO APIC...we must
* not touch this ( and it ' s already covered by the fixmap ) , so
* forcibly insert it into the resource tree */
if ( pci_resource_start ( pdev , 0 ) & & pci_resource_len ( pdev , 0 ) )
insert_resource ( & iomem_resource , & pdev - > resource [ 0 ] ) ;
/* The next five BARs all seem to be rubbish, so just clean
* them out */
for ( i = 1 ; i < 6 ; i + + ) {
memset ( & pdev - > resource [ i ] , 0 , sizeof ( pdev - > resource [ i ] ) ) ;
}
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_EESSC , quirk_alder_ioapic ) ;
2005-04-17 02:20:36 +04:00
# endif
static void __devinit quirk_pcie_mch ( struct pci_dev * pdev )
{
pcie_mch_quirk = 1 ;
}
2007-11-22 02:07:13 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_E7520_MCH , quirk_pcie_mch ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_E7320_MCH , quirk_pcie_mch ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_E7525_MCH , quirk_pcie_mch ) ;
2005-04-17 02:20:36 +04:00
2005-08-17 02:15:58 +04:00
/*
* It ' s possible for the MSI to get corrupted if shpc and acpi
* are used together on certain PXH - based systems .
*/
static void __devinit quirk_pcie_pxh ( struct pci_dev * dev )
{
2007-03-05 11:30:07 +03:00
pci_msi_off ( dev ) ;
2005-08-17 02:15:58 +04:00
dev - > no_msi = 1 ;
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " PXH quirk detected; SHPC device MSI disabled \n " ) ;
2005-08-17 02:15:58 +04:00
}
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXHD_0 , quirk_pcie_pxh ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXHD_1 , quirk_pcie_pxh ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXH_0 , quirk_pcie_pxh ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXH_1 , quirk_pcie_pxh ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXHV , quirk_pcie_pxh ) ;
2006-07-12 19:59:00 +04:00
/*
* Some Intel PCI Express chipsets have trouble with downstream
* device power management .
*/
static void quirk_intel_pcie_pm ( struct pci_dev * dev )
{
pci_pm_d3_delay = 120 ;
dev - > no_d1d2 = 1 ;
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25e2 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25e3 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25e4 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25e5 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25e6 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25e7 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25f7 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25f8 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25f9 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x25fa , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2601 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2602 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2603 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2604 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2605 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2606 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2607 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2608 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x2609 , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x260a , quirk_intel_pcie_pm ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x260b , quirk_intel_pcie_pm ) ;
2005-08-17 02:15:58 +04:00
2008-06-11 18:35:16 +04:00
# ifdef CONFIG_X86_IO_APIC
2008-06-11 18:35:17 +04:00
/*
* Boot interrupts on some chipsets cannot be turned off . For these chipsets ,
* remap the original interrupt in the linux kernel to the boot interrupt , so
* that a PCI device ' s interrupt handler is installed on the boot interrupt
* line instead .
*/
static void quirk_reroute_to_boot_interrupts_intel ( struct pci_dev * dev )
{
2008-07-15 15:48:55 +04:00
if ( noioapicquirk | | noioapicreroute )
2008-06-11 18:35:17 +04:00
return ;
dev - > irq_reroute_variant = INTEL_IRQ_REROUTE_VARIANT ;
printk ( KERN_INFO " PCI quirk: reroute interrupts for 0x%04x:0x%04x \n " ,
dev - > vendor , dev - > device ) ;
return ;
}
2008-07-08 17:59:48 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80333_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80333_1 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ESB2_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXH_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXH_1 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXHV , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80332_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80332_1 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80333_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80333_1 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ESB2_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXH_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXH_1 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_PXHV , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80332_0 , quirk_reroute_to_boot_interrupts_intel ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_80332_1 , quirk_reroute_to_boot_interrupts_intel ) ;
2008-06-11 18:35:17 +04:00
2008-06-11 18:35:16 +04:00
/*
* On some chipsets we can disable the generation of legacy INTx boot
* interrupts .
*/
/*
* IO - APIC1 on 6300 ESB generates boot interrupts , see intel order no
* 300641 - 004U S , section 5.7 .3 .
*/
# define INTEL_6300_IOAPIC_ABAR 0x40
# define INTEL_6300_DISABLE_BOOT_IRQ (1<<14)
static void quirk_disable_intel_boot_interrupt ( struct pci_dev * dev )
{
u16 pci_config_word ;
if ( noioapicquirk )
return ;
pci_read_config_word ( dev , INTEL_6300_IOAPIC_ABAR , & pci_config_word ) ;
pci_config_word | = INTEL_6300_DISABLE_BOOT_IRQ ;
pci_write_config_word ( dev , INTEL_6300_IOAPIC_ABAR , pci_config_word ) ;
printk ( KERN_INFO " disabled boot interrupt on device 0x%04x:0x%04x \n " ,
dev - > vendor , dev - > device ) ;
}
2008-07-08 17:59:48 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ESB_10 , quirk_disable_intel_boot_interrupt ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_ESB_10 , quirk_disable_intel_boot_interrupt ) ;
2008-07-08 17:59:47 +04:00
/*
* disable boot interrupts on HT - 1000
*/
# define BC_HT1000_FEATURE_REG 0x64
# define BC_HT1000_PIC_REGS_ENABLE (1<<0)
# define BC_HT1000_MAP_IDX 0xC00
# define BC_HT1000_MAP_DATA 0xC01
static void quirk_disable_broadcom_boot_interrupt ( struct pci_dev * dev )
{
u32 pci_config_dword ;
u8 irq ;
if ( noioapicquirk )
return ;
pci_read_config_dword ( dev , BC_HT1000_FEATURE_REG , & pci_config_dword ) ;
pci_write_config_dword ( dev , BC_HT1000_FEATURE_REG , pci_config_dword |
BC_HT1000_PIC_REGS_ENABLE ) ;
for ( irq = 0x10 ; irq < 0x10 + 32 ; irq + + ) {
outb ( irq , BC_HT1000_MAP_IDX ) ;
outb ( 0x00 , BC_HT1000_MAP_DATA ) ;
}
pci_write_config_dword ( dev , BC_HT1000_FEATURE_REG , pci_config_dword ) ;
printk ( KERN_INFO " disabled boot interrupts on PCI device "
" 0x%04x:0x%04x \n " , dev - > vendor , dev - > device ) ;
}
2008-07-08 17:59:48 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_SERVERWORKS , PCI_DEVICE_ID_SERVERWORKS_HT1000SB , quirk_disable_broadcom_boot_interrupt ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_SERVERWORKS , PCI_DEVICE_ID_SERVERWORKS_HT1000SB , quirk_disable_broadcom_boot_interrupt ) ;
2008-07-08 17:59:48 +04:00
/*
* disable boot interrupts on AMD and ATI chipsets
*/
/*
* NOIOAMODE needs to be disabled to disable " boot interrupts " . For AMD 8131
* rev . A0 and B0 , NOIOAMODE needs to be disabled anyway to fix IO - APIC mode
* ( due to an erratum ) .
*/
# define AMD_813X_MISC 0x40
# define AMD_813X_NOIOAMODE (1<<0)
2009-02-26 21:46:48 +03:00
# define AMD_813X_REV_B2 0x13
2008-07-08 17:59:48 +04:00
static void quirk_disable_amd_813x_boot_interrupt ( struct pci_dev * dev )
{
u32 pci_config_dword ;
if ( noioapicquirk )
return ;
2009-02-26 21:46:48 +03:00
if ( dev - > revision = = AMD_813X_REV_B2 )
return ;
2008-07-08 17:59:48 +04:00
pci_read_config_dword ( dev , AMD_813X_MISC , & pci_config_dword ) ;
pci_config_dword & = ~ AMD_813X_NOIOAMODE ;
pci_write_config_dword ( dev , AMD_813X_MISC , pci_config_dword ) ;
printk ( KERN_INFO " disabled boot interrupts on PCI device "
" 0x%04x:0x%04x \n " , dev - > vendor , dev - > device ) ;
}
2008-07-08 17:59:48 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8131_BRIDGE , quirk_disable_amd_813x_boot_interrupt ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8132_BRIDGE , quirk_disable_amd_813x_boot_interrupt ) ;
2008-07-08 17:59:48 +04:00
# define AMD_8111_PCI_IRQ_ROUTING 0x56
static void quirk_disable_amd_8111_boot_interrupt ( struct pci_dev * dev )
{
u16 pci_config_word ;
if ( noioapicquirk )
return ;
pci_read_config_word ( dev , AMD_8111_PCI_IRQ_ROUTING , & pci_config_word ) ;
if ( ! pci_config_word ) {
printk ( KERN_INFO " boot interrupts on PCI device 0x%04x:0x%04x "
" already disabled \n " ,
dev - > vendor , dev - > device ) ;
return ;
}
pci_write_config_word ( dev , AMD_8111_PCI_IRQ_ROUTING , 0 ) ;
printk ( KERN_INFO " disabled boot interrupts on PCI device "
" 0x%04x:0x%04x \n " , dev - > vendor , dev - > device ) ;
}
2008-07-08 17:59:48 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8111_SMBUS , quirk_disable_amd_8111_boot_interrupt ) ;
DECLARE_PCI_FIXUP_RESUME ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8111_SMBUS , quirk_disable_amd_8111_boot_interrupt ) ;
2008-06-11 18:35:16 +04:00
# endif /* CONFIG_X86_IO_APIC */
2007-02-07 20:18:45 +03:00
/*
* Toshiba TC86C001 IDE controller reports the standard 8 - byte BAR0 size
* but the PIO transfers won ' t work if BAR0 falls at the odd 8 bytes .
* Re - allocate the region if needed . . .
*/
static void __init quirk_tc86c001_ide ( struct pci_dev * dev )
{
struct resource * r = & dev - > resource [ 0 ] ;
if ( r - > start & 0x8 ) {
r - > start = 0 ;
r - > end = 0xf ;
}
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_TOSHIBA_2 ,
PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE ,
quirk_tc86c001_ide ) ;
2005-04-17 02:20:36 +04:00
static void __devinit quirk_netmos ( struct pci_dev * dev )
{
unsigned int num_parallel = ( dev - > subsystem_device & 0xf0 ) > > 4 ;
unsigned int num_serial = dev - > subsystem_device & 0xf ;
/*
* These Netmos parts are multiport serial devices with optional
* parallel ports . Even when parallel ports are present , they
* are identified as class SERIAL , which means the serial driver
* will claim them . To prevent this , mark them as class OTHER .
* These combo devices should be claimed by parport_serial .
*
* The subdevice ID is of the form 0x00 PS , where < P > is the number
* of parallel ports and < S > is the number of serial ports .
*/
switch ( dev - > device ) {
2008-12-08 18:19:14 +03:00
case PCI_DEVICE_ID_NETMOS_9835 :
/* Well, this rule doesn't hold for the following 9835 device */
if ( dev - > subsystem_vendor = = PCI_VENDOR_ID_IBM & &
dev - > subsystem_device = = 0x0299 )
return ;
2005-04-17 02:20:36 +04:00
case PCI_DEVICE_ID_NETMOS_9735 :
case PCI_DEVICE_ID_NETMOS_9745 :
case PCI_DEVICE_ID_NETMOS_9845 :
case PCI_DEVICE_ID_NETMOS_9855 :
if ( ( dev - > class > > 8 ) = = PCI_CLASS_COMMUNICATION_SERIAL & &
num_parallel ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Netmos %04x (%u parallel, "
2005-04-17 02:20:36 +04:00
" %u serial); changing class SERIAL to OTHER "
" (use parport_serial) \n " ,
dev - > device , num_parallel , num_serial ) ;
dev - > class = ( PCI_CLASS_COMMUNICATION_OTHER < < 8 ) |
( dev - > class & 0xff ) ;
}
}
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_NETMOS , PCI_ANY_ID , quirk_netmos ) ;
2006-04-05 16:47:00 +04:00
static void __devinit quirk_e100_interrupt ( struct pci_dev * dev )
{
2007-12-18 00:39:27 +03:00
u16 command , pmcsr ;
2006-04-05 16:47:00 +04:00
u8 __iomem * csr ;
u8 cmd_hi ;
2007-12-18 00:39:27 +03:00
int pm ;
2006-04-05 16:47:00 +04:00
switch ( dev - > device ) {
/* PCI IDs taken from drivers/net/e100.c */
case 0x1029 :
case 0x1030 . . . 0x1034 :
case 0x1038 . . . 0x103E :
case 0x1050 . . . 0x1057 :
case 0x1059 :
case 0x1064 . . . 0x106B :
case 0x1091 . . . 0x1095 :
case 0x1209 :
case 0x1229 :
case 0x2449 :
case 0x2459 :
case 0x245D :
case 0x27DC :
break ;
default :
return ;
}
/*
* Some firmware hands off the e100 with interrupts enabled ,
* which can cause a flood of interrupts if packets are
* received before the driver attaches to the device . So
* disable all e100 interrupts here . The driver will
* re - enable them when it ' s ready .
*/
pci_read_config_word ( dev , PCI_COMMAND , & command ) ;
2007-09-29 03:06:21 +04:00
if ( ! ( command & PCI_COMMAND_MEMORY ) | | ! pci_resource_start ( dev , 0 ) )
2006-04-05 16:47:00 +04:00
return ;
2007-12-18 00:39:27 +03:00
/*
* Check that the device is in the D0 power state . If it ' s not ,
* there is no point to look any further .
*/
pm = pci_find_capability ( dev , PCI_CAP_ID_PM ) ;
if ( pm ) {
pci_read_config_word ( dev , pm + PCI_PM_CTRL , & pmcsr ) ;
if ( ( pmcsr & PCI_PM_CTRL_STATE_MASK ) ! = PCI_D0 )
return ;
}
2007-09-29 03:06:21 +04:00
/* Convert from PCI bus to resource space. */
csr = ioremap ( pci_resource_start ( dev , 0 ) , 8 ) ;
2006-04-05 16:47:00 +04:00
if ( ! csr ) {
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " Can't map e100 registers \n " ) ;
2006-04-05 16:47:00 +04:00
return ;
}
cmd_hi = readb ( csr + 3 ) ;
if ( cmd_hi = = 0 ) {
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " Firmware left e100 interrupts enabled; "
" disabling \n " ) ;
2006-04-05 16:47:00 +04:00
writeb ( 1 , csr + 3 ) ;
}
iounmap ( csr ) ;
}
2007-07-03 13:03:18 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , PCI_ANY_ID , quirk_e100_interrupt ) ;
2005-11-01 01:43:56 +03:00
2009-03-05 21:57:28 +03:00
/*
* The 82575 and 82598 may experience data corruption issues when transitioning
* out of L0S . To prevent this we need to disable L0S on the pci - e link
*/
static void __devinit quirk_disable_aspm_l0s ( struct pci_dev * dev )
{
dev_info ( & dev - > dev , " Disabling L0s \n " ) ;
pci_disable_link_state ( dev , PCIE_LINK_STATE_L0S ) ;
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10a7 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10a9 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10b6 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10c6 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10c7 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10c8 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10d6 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10db , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10dd , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10e1 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10ec , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10f1 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x10f4 , quirk_disable_aspm_l0s ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x1508 , quirk_disable_aspm_l0s ) ;
2005-11-01 01:43:56 +03:00
static void __devinit fixup_rev1_53c810 ( struct pci_dev * dev )
{
/* rev 1 ncr53c810 chips don't set the class at all which means
* they don ' t get their resources remapped . Fix that here .
*/
if ( dev - > class = = PCI_CLASS_NOT_DEFINED ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " NCR 53c810 rev 1 detected; setting PCI class \n " ) ;
2005-11-01 01:43:56 +03:00
dev - > class = PCI_CLASS_STORAGE_SCSI ;
}
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_NCR , PCI_DEVICE_ID_NCR_53C810 , fixup_rev1_53c810 ) ;
2005-12-05 15:06:43 +03:00
/* Enable 1k I/O space granularity on the Intel P64H2 */
static void __devinit quirk_p64h2_1k_io ( struct pci_dev * dev )
{
u16 en1k ;
u8 io_base_lo , io_limit_lo ;
unsigned long base , limit ;
struct resource * res = dev - > resource + PCI_BRIDGE_RESOURCES ;
pci_read_config_word ( dev , 0x40 , & en1k ) ;
if ( en1k & 0x200 ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Enable I/O Space to 1KB granularity \n " ) ;
2005-12-05 15:06:43 +03:00
pci_read_config_byte ( dev , PCI_IO_BASE , & io_base_lo ) ;
pci_read_config_byte ( dev , PCI_IO_LIMIT , & io_limit_lo ) ;
base = ( io_base_lo & ( PCI_IO_RANGE_MASK | 0x0c ) ) < < 8 ;
limit = ( io_limit_lo & ( PCI_IO_RANGE_MASK | 0x0c ) ) < < 8 ;
if ( base < = limit ) {
res - > start = base ;
res - > end = limit + 0x3ff ;
}
}
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , 0x1460 , quirk_p64h2_1k_io ) ;
2006-12-21 22:34:57 +03:00
/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2
* The IOBL_ADR gets re - written to 4 k boundaries in pci_setup_bridge ( )
* in drivers / pci / setup - bus . c
*/
static void __devinit quirk_p64h2_1k_io_fix_iobl ( struct pci_dev * dev )
{
u16 en1k , iobl_adr , iobl_adr_1k ;
struct resource * res = dev - > resource + PCI_BRIDGE_RESOURCES ;
pci_read_config_word ( dev , 0x40 , & en1k ) ;
if ( en1k & 0x200 ) {
pci_read_config_word ( dev , PCI_IO_BASE , & iobl_adr ) ;
iobl_adr_1k = iobl_adr | ( res - > start > > 8 ) | ( res - > end & 0xfc00 ) ;
if ( iobl_adr ! = iobl_adr_1k ) {
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity \n " ,
2006-12-21 22:34:57 +03:00
iobl_adr , iobl_adr_1k ) ;
pci_write_config_word ( dev , PCI_IO_BASE , iobl_adr_1k ) ;
}
}
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_INTEL , 0x1460 , quirk_p64h2_1k_io_fix_iobl ) ;
2006-06-13 22:35:42 +04:00
/* Under some circumstances, AER is not linked with extended capabilities.
* Force it to be linked by setting the corresponding control bit in the
* config space .
*/
2006-12-05 02:14:45 +03:00
static void quirk_nvidia_ck804_pcie_aer_ext_cap ( struct pci_dev * dev )
2006-06-13 22:35:42 +04:00
{
uint8_t b ;
if ( pci_read_config_byte ( dev , 0xf41 , & b ) = = 0 ) {
if ( ! ( b & 0x20 ) ) {
pci_write_config_byte ( dev , 0xf41 , b | 0x20 ) ;
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev ,
" Linking AER extended capability \n " ) ;
2006-06-13 22:35:42 +04:00
}
}
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_NVIDIA , PCI_DEVICE_ID_NVIDIA_CK804_PCIE ,
quirk_nvidia_ck804_pcie_aer_ext_cap ) ;
2008-05-15 23:51:31 +04:00
DECLARE_PCI_FIXUP_RESUME_EARLY ( PCI_VENDOR_ID_NVIDIA , PCI_DEVICE_ID_NVIDIA_CK804_PCIE ,
2006-12-05 02:14:45 +03:00
quirk_nvidia_ck804_pcie_aer_ext_cap ) ;
2006-06-13 22:35:42 +04:00
2007-11-02 02:14:54 +03:00
static void __devinit quirk_via_cx700_pci_parking_caching ( struct pci_dev * dev )
{
/*
* Disable PCI Bus Parking and PCI Master read caching on CX700
* which causes unspecified timing errors with a VT6212L on the PCI
* bus leading to USB2 .0 packet loss . The defaults are that these
* features are turned off but some BIOSes turn them on .
*/
uint8_t b ;
if ( pci_read_config_byte ( dev , 0x76 , & b ) = = 0 ) {
if ( b & 0x40 ) {
/* Turn off PCI Bus Parking */
pci_write_config_byte ( dev , 0x76 , b ^ 0x40 ) ;
2008-03-30 23:58:59 +04:00
dev_info ( & dev - > dev ,
" Disabling VIA CX700 PCI parking \n " ) ;
}
}
if ( pci_read_config_byte ( dev , 0x72 , & b ) = = 0 ) {
if ( b ! = 0 ) {
2007-11-02 02:14:54 +03:00
/* Turn off PCI Master read caching */
pci_write_config_byte ( dev , 0x72 , 0x0 ) ;
2008-03-30 23:58:59 +04:00
/* Set PCI Master Bus time-out to "1x16 PCLK" */
2007-11-02 02:14:54 +03:00
pci_write_config_byte ( dev , 0x75 , 0x1 ) ;
2008-03-30 23:58:59 +04:00
/* Disable "Read FIFO Timer" */
2007-11-02 02:14:54 +03:00
pci_write_config_byte ( dev , 0x77 , 0x0 ) ;
2008-03-01 02:12:18 +03:00
dev_info ( & dev - > dev ,
2008-03-30 23:58:59 +04:00
" Disabling VIA CX700 PCI caching \n " ) ;
2007-11-02 02:14:54 +03:00
}
}
}
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_VIA , 0x324e , quirk_via_cx700_pci_parking_caching ) ;
2008-07-02 21:59:04 +04:00
/*
* For Broadcom 5706 , 5708 , 5709 rev . A nics , any read beyond the
* VPD end tag will hang the device . This problem was initially
* observed when a vpd entry was created in sysfs
* ( ' / sys / bus / pci / devices / < id > / vpd ' ) . A read to this sysfs entry
* will dump 32 k of data . Reading a full 32 k will cause an access
* beyond the VPD end tag causing the device to hang . Once the device
* is hung , the bnx2 driver will not be able to reset the device .
* We believe that it is legal to read beyond the end tag and
* therefore the solution is to limit the read / write length .
*/
static void __devinit quirk_brcm_570x_limit_vpd ( struct pci_dev * dev )
{
2008-07-31 22:27:31 +04:00
/*
2008-08-08 04:31:45 +04:00
* Only disable the VPD capability for 5706 , 5706 S , 5708 ,
* 5708 S and 5709 rev . A
2008-07-31 22:27:31 +04:00
*/
2008-07-02 21:59:04 +04:00
if ( ( dev - > device = = PCI_DEVICE_ID_NX2_5706 ) | |
2008-08-08 04:31:45 +04:00
( dev - > device = = PCI_DEVICE_ID_NX2_5706S ) | |
2008-07-02 21:59:04 +04:00
( dev - > device = = PCI_DEVICE_ID_NX2_5708 ) | |
2008-07-31 22:27:31 +04:00
( dev - > device = = PCI_DEVICE_ID_NX2_5708S ) | |
2008-07-02 21:59:04 +04:00
( ( dev - > device = = PCI_DEVICE_ID_NX2_5709 ) & &
( dev - > revision & 0xf0 ) = = 0x0 ) ) {
if ( dev - > vpd )
dev - > vpd - > len = 0x80 ;
}
}
2008-10-28 09:44:11 +03:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_NX2_5706 ,
quirk_brcm_570x_limit_vpd ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_NX2_5706S ,
quirk_brcm_570x_limit_vpd ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_NX2_5708 ,
quirk_brcm_570x_limit_vpd ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_NX2_5708S ,
quirk_brcm_570x_limit_vpd ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_NX2_5709 ,
quirk_brcm_570x_limit_vpd ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_NX2_5709S ,
quirk_brcm_570x_limit_vpd ) ;
2008-07-02 21:59:04 +04:00
2009-05-13 00:49:26 +04:00
/* Originally in EDAC sources for i82875P:
* Intel tells BIOS developers to hide device 6 which
* configures the overflow device access containing
* the DRBs - this is where we expose device 6.
* http : //www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
*/
static void __devinit quirk_unhide_mch_dev6 ( struct pci_dev * dev )
{
u8 reg ;
if ( pci_read_config_byte ( dev , 0xF4 , & reg ) = = 0 & & ! ( reg & 0x02 ) ) {
dev_info ( & dev - > dev , " Enabling MCH 'Overflow' Device \n " ) ;
pci_write_config_byte ( dev , 0xF4 , reg | 0x02 ) ;
}
}
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82865_HB ,
quirk_unhide_mch_dev6 ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_82875_HB ,
quirk_unhide_mch_dev6 ) ;
2006-08-31 09:54:56 +04:00
# ifdef CONFIG_PCI_MSI
2007-05-31 11:40:48 +04:00
/* Some chipsets do not support MSI. We cannot easily rely on setting
* PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
* some other busses controlled by the chipset even if Linux is not
* aware of it . Instead of setting the flag on all busses in the
* machine , simply disable MSI globally .
2006-08-31 09:54:56 +04:00
*/
2007-05-31 11:40:48 +04:00
static void __init quirk_disable_all_msi ( struct pci_dev * dev )
2006-08-31 09:54:56 +04:00
{
2007-01-25 11:34:07 +03:00
pci_no_msi ( ) ;
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " MSI quirk detected; MSI disabled \n " ) ;
2006-08-31 09:54:56 +04:00
}
2007-05-31 11:40:48 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_SERVERWORKS , PCI_DEVICE_ID_SERVERWORKS_GCNB_LE , quirk_disable_all_msi ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_RS400_200 , quirk_disable_all_msi ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_RS480 , quirk_disable_all_msi ) ;
2008-07-04 20:59:32 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_VT3336 , quirk_disable_all_msi ) ;
2007-05-27 02:01:04 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_VT3351 , quirk_disable_all_msi ) ;
2009-04-03 17:34:00 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_VIA , PCI_DEVICE_ID_VIA_VT3364 , quirk_disable_all_msi ) ;
2006-08-31 09:54:56 +04:00
/* Disable MSI on chipsets that are known to not support it */
static void __devinit quirk_disable_msi ( struct pci_dev * dev )
{
if ( dev - > subordinate ) {
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " MSI quirk detected; "
" subordinate MSI disabled \n " ) ;
2006-08-31 09:54:56 +04:00
dev - > subordinate - > bus_flags | = PCI_BUS_FLAGS_NO_MSI ;
}
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8131_BRIDGE , quirk_disable_msi ) ;
2006-08-31 09:55:32 +04:00
/* Go through the list of Hypertransport capabilities and
* return 1 if a HT MSI capability is found and enabled */
static int __devinit msi_ht_cap_enabled ( struct pci_dev * dev )
{
2006-11-22 10:26:21 +03:00
int pos , ttl = 48 ;
pos = pci_find_ht_capability ( dev , HT_CAPTYPE_MSI_MAPPING ) ;
while ( pos & & ttl - - ) {
u8 flags ;
if ( pci_read_config_byte ( dev , pos + HT_MSI_FLAGS ,
& flags ) = = 0 )
{
2007-12-18 00:09:39 +03:00
dev_info ( & dev - > dev , " Found %s HT MSI Mapping \n " ,
2006-11-22 10:26:21 +03:00
flags & HT_MSI_FLAGS_ENABLE ?
2007-12-18 00:09:39 +03:00
" enabled " : " disabled " ) ;
2006-11-22 10:26:21 +03:00
return ( flags & HT_MSI_FLAGS_ENABLE ) ! = 0 ;
2006-08-31 09:55:32 +04:00
}
2006-11-22 10:26:21 +03:00
pos = pci_find_next_ht_capability ( dev , pos ,
HT_CAPTYPE_MSI_MAPPING ) ;
2006-08-31 09:55:32 +04:00
}
return 0 ;
}
/* Check the hypertransport MSI mapping to know whether MSI is enabled or not */
static void __devinit quirk_msi_ht_cap ( struct pci_dev * dev )
{
if ( dev - > subordinate & & ! msi_ht_cap_enabled ( dev ) ) {
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " MSI quirk detected; "
" subordinate MSI disabled \n " ) ;
2006-08-31 09:55:32 +04:00
dev - > subordinate - > bus_flags | = PCI_BUS_FLAGS_NO_MSI ;
}
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_SERVERWORKS , PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE ,
quirk_msi_ht_cap ) ;
2007-12-14 03:09:25 +03:00
2006-08-31 09:55:32 +04:00
/* The nVidia CK804 chipset may have 2 HT MSI mappings.
* MSI are supported if the MSI capability set in any of these mappings .
*/
static void __devinit quirk_nvidia_ck804_msi_ht_cap ( struct pci_dev * dev )
{
struct pci_dev * pdev ;
if ( ! dev - > subordinate )
return ;
/* check HT MSI cap on this chipset and the root one.
* a single one having MSI is enough to be sure that MSI are supported .
*/
2006-10-11 01:39:00 +04:00
pdev = pci_get_slot ( dev - > bus , 0 ) ;
2006-12-05 02:14:48 +03:00
if ( ! pdev )
return ;
2006-12-03 22:55:34 +03:00
if ( ! msi_ht_cap_enabled ( dev ) & & ! msi_ht_cap_enabled ( pdev ) ) {
2007-12-18 00:09:39 +03:00
dev_warn ( & dev - > dev , " MSI quirk detected; "
" subordinate MSI disabled \n " ) ;
2006-08-31 09:55:32 +04:00
dev - > subordinate - > bus_flags | = PCI_BUS_FLAGS_NO_MSI ;
}
2006-10-11 01:39:00 +04:00
pci_dev_put ( pdev ) ;
2006-08-31 09:55:32 +04:00
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_NVIDIA , PCI_DEVICE_ID_NVIDIA_CK804_PCIE ,
quirk_nvidia_ck804_msi_ht_cap ) ;
2007-10-25 12:16:30 +04:00
2008-03-01 02:04:39 +03:00
/* Force enable MSI mapping capability on HT bridges */
static void __devinit ht_enable_msi_mapping ( struct pci_dev * dev )
2008-02-05 10:50:13 +03:00
{
int pos , ttl = 48 ;
pos = pci_find_ht_capability ( dev , HT_CAPTYPE_MSI_MAPPING ) ;
while ( pos & & ttl - - ) {
u8 flags ;
if ( pci_read_config_byte ( dev , pos + HT_MSI_FLAGS ,
& flags ) = = 0 ) {
dev_info ( & dev - > dev , " Enabling HT MSI Mapping \n " ) ;
pci_write_config_byte ( dev , pos + HT_MSI_FLAGS ,
flags | HT_MSI_FLAGS_ENABLE ) ;
}
pos = pci_find_next_ht_capability ( dev , pos ,
HT_CAPTYPE_MSI_MAPPING ) ;
}
}
2008-03-01 02:04:39 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_SERVERWORKS ,
PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB ,
ht_enable_msi_mapping ) ;
2008-02-05 10:50:13 +03:00
2009-02-18 07:40:09 +03:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_AMD , PCI_DEVICE_ID_AMD_8132_BRIDGE ,
ht_enable_msi_mapping ) ;
2008-11-21 07:42:25 +03:00
/* The P5N32-SLI Premium motherboard from Asus has a problem with msi
* for the MCP55 NIC . It is not yet determined whether the msi problem
* also affects other devices . As for now , turn off msi for this device .
*/
static void __devinit nvenet_msi_disable ( struct pci_dev * dev )
{
if ( dmi_name_in_vendors ( " P5N32-SLI PREMIUM " ) ) {
dev_info ( & dev - > dev ,
" Disabling msi for MCP55 NIC on P5N32-SLI Premium \n " ) ;
dev - > no_msi = 1 ;
}
}
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_NVIDIA ,
PCI_DEVICE_ID_NVIDIA_NVENET_15 ,
nvenet_msi_disable ) ;
2009-03-21 05:29:41 +03:00
static int __devinit ht_check_msi_mapping ( struct pci_dev * dev )
{
int pos , ttl = 48 ;
int found = 0 ;
/* check if there is HT MSI cap or enabled on this device */
pos = pci_find_ht_capability ( dev , HT_CAPTYPE_MSI_MAPPING ) ;
while ( pos & & ttl - - ) {
u8 flags ;
if ( found < 1 )
found = 1 ;
if ( pci_read_config_byte ( dev , pos + HT_MSI_FLAGS ,
& flags ) = = 0 ) {
if ( flags & HT_MSI_FLAGS_ENABLE ) {
if ( found < 2 ) {
found = 2 ;
break ;
}
}
}
pos = pci_find_next_ht_capability ( dev , pos ,
HT_CAPTYPE_MSI_MAPPING ) ;
}
return found ;
}
static int __devinit host_bridge_with_leaf ( struct pci_dev * host_bridge )
{
struct pci_dev * dev ;
int pos ;
int i , dev_no ;
int found = 0 ;
dev_no = host_bridge - > devfn > > 3 ;
for ( i = dev_no + 1 ; i < 0x20 ; i + + ) {
dev = pci_get_slot ( host_bridge - > bus , PCI_DEVFN ( i , 0 ) ) ;
if ( ! dev )
continue ;
/* found next host bridge ?*/
pos = pci_find_ht_capability ( dev , HT_CAPTYPE_SLAVE ) ;
if ( pos ! = 0 ) {
pci_dev_put ( dev ) ;
break ;
}
if ( ht_check_msi_mapping ( dev ) ) {
found = 1 ;
pci_dev_put ( dev ) ;
break ;
}
pci_dev_put ( dev ) ;
}
return found ;
}
2009-03-29 23:30:05 +04:00
# define PCI_HT_CAP_SLAVE_CTRL0 4 /* link control */
# define PCI_HT_CAP_SLAVE_CTRL1 8 /* link control to */
static int __devinit is_end_of_ht_chain ( struct pci_dev * dev )
{
int pos , ctrl_off ;
int end = 0 ;
u16 flags , ctrl ;
pos = pci_find_ht_capability ( dev , HT_CAPTYPE_SLAVE ) ;
if ( ! pos )
goto out ;
pci_read_config_word ( dev , pos + PCI_CAP_FLAGS , & flags ) ;
ctrl_off = ( ( flags > > 10 ) & 1 ) ?
PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1 ;
pci_read_config_word ( dev , pos + ctrl_off , & ctrl ) ;
if ( ctrl & ( 1 < < 6 ) )
end = 1 ;
out :
return end ;
}
2009-02-23 22:51:59 +03:00
static void __devinit nv_ht_enable_msi_mapping ( struct pci_dev * dev )
2008-02-05 10:50:13 +03:00
{
struct pci_dev * host_bridge ;
2009-02-23 22:51:59 +03:00
int pos ;
int i , dev_no ;
int found = 0 ;
dev_no = dev - > devfn > > 3 ;
for ( i = dev_no ; i > = 0 ; i - - ) {
host_bridge = pci_get_slot ( dev - > bus , PCI_DEVFN ( i , 0 ) ) ;
if ( ! host_bridge )
continue ;
pos = pci_find_ht_capability ( host_bridge , HT_CAPTYPE_SLAVE ) ;
if ( pos ! = 0 ) {
found = 1 ;
break ;
}
pci_dev_put ( host_bridge ) ;
}
if ( ! found )
return ;
2009-03-29 23:30:05 +04:00
/* don't enable end_device/host_bridge with leaf directly here */
if ( host_bridge = = dev & & is_end_of_ht_chain ( host_bridge ) & &
host_bridge_with_leaf ( host_bridge ) )
2009-03-21 05:29:41 +03:00
goto out ;
2009-02-23 22:51:59 +03:00
/* root did that ! */
if ( msi_ht_cap_enabled ( host_bridge ) )
goto out ;
ht_enable_msi_mapping ( dev ) ;
out :
pci_dev_put ( host_bridge ) ;
}
static void __devinit ht_disable_msi_mapping ( struct pci_dev * dev )
{
int pos , ttl = 48 ;
pos = pci_find_ht_capability ( dev , HT_CAPTYPE_MSI_MAPPING ) ;
while ( pos & & ttl - - ) {
u8 flags ;
if ( pci_read_config_byte ( dev , pos + HT_MSI_FLAGS ,
& flags ) = = 0 ) {
2009-03-06 12:10:35 +03:00
dev_info ( & dev - > dev , " Disabling HT MSI Mapping \n " ) ;
2009-02-23 22:51:59 +03:00
pci_write_config_byte ( dev , pos + HT_MSI_FLAGS ,
flags & ~ HT_MSI_FLAGS_ENABLE ) ;
}
pos = pci_find_next_ht_capability ( dev , pos ,
HT_CAPTYPE_MSI_MAPPING ) ;
}
}
2009-03-21 05:29:41 +03:00
static void __devinit __nv_msi_ht_cap_quirk ( struct pci_dev * dev , int all )
2009-02-23 22:51:59 +03:00
{
struct pci_dev * host_bridge ;
int pos ;
int found ;
/* check if there is HT MSI cap or enabled on this device */
found = ht_check_msi_mapping ( dev ) ;
/* no HT MSI CAP */
if ( found = = 0 )
return ;
2008-02-05 10:50:13 +03:00
/*
* HT MSI mapping should be disabled on devices that are below
* a non - Hypertransport host bridge . Locate the host bridge . . .
*/
host_bridge = pci_get_bus_and_slot ( 0 , PCI_DEVFN ( 0 , 0 ) ) ;
if ( host_bridge = = NULL ) {
dev_warn ( & dev - > dev ,
" nv_msi_ht_cap_quirk didn't locate host bridge \n " ) ;
return ;
}
pos = pci_find_ht_capability ( host_bridge , HT_CAPTYPE_SLAVE ) ;
if ( pos ! = 0 ) {
/* Host bridge is to HT */
2009-02-23 22:51:59 +03:00
if ( found = = 1 ) {
/* it is not enabled, try to enable it */
2009-03-21 05:29:41 +03:00
if ( all )
ht_enable_msi_mapping ( dev ) ;
else
nv_ht_enable_msi_mapping ( dev ) ;
2009-02-23 22:51:59 +03:00
}
2008-02-05 10:50:13 +03:00
return ;
}
2009-02-23 22:51:59 +03:00
/* HT MSI is not enabled */
if ( found = = 1 )
return ;
2008-02-05 10:50:13 +03:00
2009-02-23 22:51:59 +03:00
/* Host bridge is not to HT, disable HT MSI mapping on this device */
ht_disable_msi_mapping ( dev ) ;
2008-02-05 10:50:13 +03:00
}
2009-03-21 05:29:41 +03:00
static void __devinit nv_msi_ht_cap_quirk_all ( struct pci_dev * dev )
{
return __nv_msi_ht_cap_quirk ( dev , 1 ) ;
}
static void __devinit nv_msi_ht_cap_quirk_leaf ( struct pci_dev * dev )
{
return __nv_msi_ht_cap_quirk ( dev , 0 ) ;
}
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_NVIDIA , PCI_ANY_ID , nv_msi_ht_cap_quirk_leaf ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_AL , PCI_ANY_ID , nv_msi_ht_cap_quirk_all ) ;
2008-02-05 10:50:13 +03:00
2007-10-25 12:16:30 +04:00
static void __devinit quirk_msi_intx_disable_bug ( struct pci_dev * dev )
{
dev - > dev_flags | = PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG ;
}
2008-01-25 09:46:24 +03:00
static void __devinit quirk_msi_intx_disable_ati_bug ( struct pci_dev * dev )
{
struct pci_dev * p ;
/* SB700 MSI issue will be fixed at HW level from revision A21,
* we need check PCI REVISION ID of SMBus controller to get SB700
* revision .
*/
p = pci_get_device ( PCI_VENDOR_ID_ATI , PCI_DEVICE_ID_ATI_SBX00_SMBUS ,
NULL ) ;
if ( ! p )
return ;
if ( ( p - > revision < 0x3B ) & & ( p - > revision > = 0x30 ) )
dev - > dev_flags | = PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG ;
pci_dev_put ( p ) ;
}
2007-10-25 12:16:30 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_TIGON3_5780 ,
quirk_msi_intx_disable_bug ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_TIGON3_5780S ,
quirk_msi_intx_disable_bug ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_TIGON3_5714 ,
quirk_msi_intx_disable_bug ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_TIGON3_5714S ,
quirk_msi_intx_disable_bug ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_TIGON3_5715 ,
quirk_msi_intx_disable_bug ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_BROADCOM ,
PCI_DEVICE_ID_TIGON3_5715S ,
quirk_msi_intx_disable_bug ) ;
2007-10-25 12:16:52 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4390 ,
2008-01-25 09:46:24 +03:00
quirk_msi_intx_disable_ati_bug ) ;
2007-10-25 12:16:52 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4391 ,
2008-01-25 09:46:24 +03:00
quirk_msi_intx_disable_ati_bug ) ;
2007-10-25 12:16:52 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4392 ,
2008-01-25 09:46:24 +03:00
quirk_msi_intx_disable_ati_bug ) ;
2007-10-25 12:16:52 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4393 ,
2008-01-25 09:46:24 +03:00
quirk_msi_intx_disable_ati_bug ) ;
2007-10-25 12:16:52 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4394 ,
2008-01-25 09:46:24 +03:00
quirk_msi_intx_disable_ati_bug ) ;
2007-10-25 12:16:52 +04:00
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4373 ,
quirk_msi_intx_disable_bug ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4374 ,
quirk_msi_intx_disable_bug ) ;
DECLARE_PCI_FIXUP_FINAL ( PCI_VENDOR_ID_ATI , 0x4375 ,
quirk_msi_intx_disable_bug ) ;
2006-08-31 09:54:56 +04:00
# endif /* CONFIG_PCI_MSI */
2008-08-19 12:28:24 +04:00
2009-04-03 11:18:11 +04:00
# ifdef CONFIG_PCI_IOV
/*
* For Intel 82576 SR - IOV NIC , if BIOS doesn ' t allocate resources for the
* SR - IOV BARs , zero the Flash BAR and program the SR - IOV BARs to use the
* old Flash Memory Space .
*/
static void __devinit quirk_i82576_sriov ( struct pci_dev * dev )
{
int pos , flags ;
u32 bar , start , size ;
if ( PAGE_SIZE > 0x10000 )
return ;
flags = pci_resource_flags ( dev , 0 ) ;
if ( ( flags & PCI_BASE_ADDRESS_SPACE ) ! =
PCI_BASE_ADDRESS_SPACE_MEMORY | |
( flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK ) ! =
PCI_BASE_ADDRESS_MEM_TYPE_32 )
return ;
pos = pci_find_ext_capability ( dev , PCI_EXT_CAP_ID_SRIOV ) ;
if ( ! pos )
return ;
pci_read_config_dword ( dev , pos + PCI_SRIOV_BAR , & bar ) ;
if ( bar & PCI_BASE_ADDRESS_MEM_MASK )
return ;
start = pci_resource_start ( dev , 1 ) ;
size = pci_resource_len ( dev , 1 ) ;
if ( ! start | | size ! = 0x400000 | | start & ( size - 1 ) )
return ;
pci_resource_flags ( dev , 1 ) = 0 ;
pci_write_config_dword ( dev , PCI_BASE_ADDRESS_1 , 0 ) ;
pci_write_config_dword ( dev , pos + PCI_SRIOV_BAR , start ) ;
pci_write_config_dword ( dev , pos + PCI_SRIOV_BAR + 12 , start + size / 2 ) ;
dev_info ( & dev - > dev , " use Flash Memory Space for SR-IOV BARs \n " ) ;
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , 0x10c9 , quirk_i82576_sriov ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , 0x10e6 , quirk_i82576_sriov ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , 0x10e7 , quirk_i82576_sriov ) ;
2009-05-06 14:25:42 +04:00
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , 0x10e8 , quirk_i82576_sriov ) ;
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_INTEL , 0x150a , quirk_i82576_sriov ) ;
2009-04-03 11:18:11 +04:00
# endif /* CONFIG_PCI_IOV */
2008-10-28 03:50:21 +03:00
static void pci_do_fixups ( struct pci_dev * dev , struct pci_fixup * f ,
struct pci_fixup * end )
2008-08-19 12:28:24 +04:00
{
while ( f < end ) {
if ( ( f - > vendor = = dev - > vendor | | f - > vendor = = ( u16 ) PCI_ANY_ID ) & &
2008-10-28 03:50:21 +03:00
( f - > device = = dev - > device | | f - > device = = ( u16 ) PCI_ANY_ID ) ) {
2008-09-25 06:04:33 +04:00
dev_dbg ( & dev - > dev , " calling %pF \n " , f - > hook ) ;
2008-08-19 12:28:24 +04:00
f - > hook ( dev ) ;
}
f + + ;
}
}
extern struct pci_fixup __start_pci_fixups_early [ ] ;
extern struct pci_fixup __end_pci_fixups_early [ ] ;
extern struct pci_fixup __start_pci_fixups_header [ ] ;
extern struct pci_fixup __end_pci_fixups_header [ ] ;
extern struct pci_fixup __start_pci_fixups_final [ ] ;
extern struct pci_fixup __end_pci_fixups_final [ ] ;
extern struct pci_fixup __start_pci_fixups_enable [ ] ;
extern struct pci_fixup __end_pci_fixups_enable [ ] ;
extern struct pci_fixup __start_pci_fixups_resume [ ] ;
extern struct pci_fixup __end_pci_fixups_resume [ ] ;
extern struct pci_fixup __start_pci_fixups_resume_early [ ] ;
extern struct pci_fixup __end_pci_fixups_resume_early [ ] ;
extern struct pci_fixup __start_pci_fixups_suspend [ ] ;
extern struct pci_fixup __end_pci_fixups_suspend [ ] ;
void pci_fixup_device ( enum pci_fixup_pass pass , struct pci_dev * dev )
{
struct pci_fixup * start , * end ;
switch ( pass ) {
case pci_fixup_early :
start = __start_pci_fixups_early ;
end = __end_pci_fixups_early ;
break ;
case pci_fixup_header :
start = __start_pci_fixups_header ;
end = __end_pci_fixups_header ;
break ;
case pci_fixup_final :
start = __start_pci_fixups_final ;
end = __end_pci_fixups_final ;
break ;
case pci_fixup_enable :
start = __start_pci_fixups_enable ;
end = __end_pci_fixups_enable ;
break ;
case pci_fixup_resume :
start = __start_pci_fixups_resume ;
end = __end_pci_fixups_resume ;
break ;
case pci_fixup_resume_early :
start = __start_pci_fixups_resume_early ;
end = __end_pci_fixups_resume_early ;
break ;
case pci_fixup_suspend :
start = __start_pci_fixups_suspend ;
end = __end_pci_fixups_suspend ;
break ;
default :
/* stupid compiler warning, you would think with an enum... */
return ;
}
pci_do_fixups ( dev , start , end ) ;
}
# else
void pci_fixup_device ( enum pci_fixup_pass pass , struct pci_dev * dev ) { }
# endif
EXPORT_SYMBOL ( pci_fixup_device ) ;