diff options
Diffstat (limited to 'arch/ia64/pci')
-rw-r--r-- | arch/ia64/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/pci/fixup.c | 69 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 75 |
3 files changed, 93 insertions, 53 deletions
diff --git a/arch/ia64/pci/Makefile b/arch/ia64/pci/Makefile index e66889e6922..fb14dc520d2 100644 --- a/arch/ia64/pci/Makefile +++ b/arch/ia64/pci/Makefile @@ -1,4 +1,4 @@ # # Makefile for the ia64-specific parts of the pci bus # -obj-y := pci.o +obj-y := pci.o fixup.o diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c new file mode 100644 index 00000000000..245dc1fedc2 --- /dev/null +++ b/arch/ia64/pci/fixup.c @@ -0,0 +1,69 @@ +/* + * Exceptions for specific devices. Usually work-arounds for fatal design flaws. + * Derived from fixup.c of i386 tree. + */ + +#include <linux/pci.h> +#include <linux/init.h> + +#include <asm/machvec.h> + +/* + * Fixup to mark boot BIOS video selected by BIOS before it changes + * + * From information provided by "Jon Smirl" <jonsmirl@gmail.com> + * + * The standard boot ROM sequence for an x86 machine uses the BIOS + * to select an initial video card for boot display. This boot video + * card will have it's BIOS copied to C0000 in system RAM. + * IORESOURCE_ROM_SHADOW is used to associate the boot video + * card with this copy. On laptops this copy has to be used since + * the main ROM may be compressed or combined with another image. + * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW + * is marked here since the boot video device will be the only enabled + * video device at this point. + */ + +static void __devinit pci_fixup_video(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + u16 config; + + if ((strcmp(platform_name, "dig") != 0) + && (strcmp(platform_name, "hpzx1") != 0)) + return; + /* Maybe, this machine supports legacy memory map. */ + + if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + return; + + /* Is VGA routed to us? */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + + /* + * From information provided by + * "David Miller" <davem@davemloft.net> + * The bridge control register is valid for PCI header + * type BRIDGE, or CARDBUS. Host to PCI controllers use + * PCI header type NORMAL. + */ + if (bridge + &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE) + ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, + &config); + if (!(config & PCI_BRIDGE_CTL_VGA)) + return; + } + bus = bus->parent; + } + pci_read_config_word(pdev, PCI_COMMAND, &config); + if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index b30be7c48ba..f4edfbf2713 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -469,10 +469,11 @@ pcibios_fixup_resources(struct pci_dev *dev, int start, int limit) } } -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) { pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES); } +EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources); static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev) { @@ -493,6 +494,7 @@ pcibios_fixup_bus (struct pci_bus *b) } list_for_each_entry(dev, &b->devices, bus_list) pcibios_fixup_device_resources(dev); + platform_pci_fixup_bus(b); return; } @@ -738,75 +740,44 @@ int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) return ret; } +/* It's defined in drivers/pci/pci.c */ +extern u8 pci_cache_line_size; + /** - * pci_cacheline_size - determine cacheline size for PCI devices - * @dev: void + * set_pci_cacheline_size - determine cacheline size for PCI devices * * We want to use the line-size of the outer-most cache. We assume * that this line-size is the same for all CPUs. * * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). - * - * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. */ -static unsigned long -pci_cacheline_size (void) +static void __init set_pci_cacheline_size(void) { u64 levels, unique_caches; s64 status; pal_cache_config_info_t cci; - static u8 cacheline_size; - - if (cacheline_size) - return cacheline_size; status = ia64_pal_cache_summary(&levels, &unique_caches); if (status != 0) { - printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", - __FUNCTION__, status); - return SMP_CACHE_BYTES; + printk(KERN_ERR "%s: ia64_pal_cache_summary() failed " + "(status=%ld)\n", __FUNCTION__, status); + return; } - status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, - &cci); + status = ia64_pal_cache_config_info(levels - 1, + /* cache_type (data_or_unified)= */ 2, &cci); if (status != 0) { - printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n", - __FUNCTION__, status); - return SMP_CACHE_BYTES; + printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed " + "(status=%ld)\n", __FUNCTION__, status); + return; } - cacheline_size = 1 << cci.pcci_line_size; - return cacheline_size; + pci_cache_line_size = (1 << cci.pcci_line_size) / 4; } -/** - * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi() - * @dev: the PCI device for which MWI is enabled - * - * For ia64, we can get the cacheline sizes from PAL. - * - * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. - */ -int -pcibios_prep_mwi (struct pci_dev *dev) -{ - unsigned long desired_linesize, current_linesize; - int rc = 0; - u8 pci_linesize; - - desired_linesize = pci_cacheline_size(); - - pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize); - current_linesize = 4 * pci_linesize; - if (desired_linesize != current_linesize) { - printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,", - pci_name(dev), current_linesize); - if (current_linesize > desired_linesize) { - printk(" expected %lu bytes instead\n", desired_linesize); - rc = -EINVAL; - } else { - printk(" correcting to %lu\n", desired_linesize); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4); - } - } - return rc; +static int __init pcibios_init(void) +{ + set_pci_cacheline_size(); + return 0; } + +subsys_initcall(pcibios_init); |