/*
* Port for PPC64 David Engebretsen, IBM Corp.
* Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
*
* Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
* Rework, based on alpha PCI code.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#undef DEBUG
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/udbg.h>
#include "pci.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
unsigned long pci_probe_only = 1;
unsigned long pci_assign_all_buses = 0;
/*
* legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch
* devices we don't have access to.
*/
unsigned long io_page_mask;
EXPORT_SYMBOL(io_page_mask);
unsigned int pcibios_assign_all_busses(void)
{
return pci_assign_all_buses;
}
/* pci_io_base -- the base address from which io bars are offsets.
* This is the lowest I/O base address (so bar values are always positive),
* and it *must* be the start of ISA space if an ISA bus exists because
* ISA drivers use hard coded offsets. If no ISA bus exists a dummy
* page is mapped and isa_io_limit prevents access to it.
*/
unsigned long isa_io_base; /* NULL if no ISA bus */
EXPORT_SYMBOL(isa_io_base);
unsigned long pci_io_base;
EXPORT_SYMBOL(pci_io_base);
void iSeries_pcibios_init(void);
LIST_HEAD(hose_list);
struct dma_mapping_ops pci_dma_ops;
EXPORT_SYMBOL(pci_dma_ops);
int global_phb_number; /* Global phb counter */
/* Cached ISA bridge dev. */
struct pci_dev *ppc64_isabridge_dev = NULL;
static void fixup_broken_pcnet32(struct pci_dev* dev)
{
if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
dev->vendor = PCI_VENDOR_ID_AMD;
pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
{
unsigned long offset = 0;
struct pci_controller *hose = pci_bus_to_host(dev->bus);
if (!hose)
return;
if (res->flags & IORESOURCE_IO)
offset = (unsigned long)hose->io_base_virt - pci_io_base;
if (res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
region->start = res->start - offset;
region->end = res->end - offset;
}
void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
unsigned long offset = 0;
struct pci_controller *hose = pci_bus_to_host(dev->bus);
if (!hose)
return;
if (res->flags & IORESOURCE_IO)
offset = (unsigned long)hose->io_base_virt - pci_io_base;
if (res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
res->start = region->start + offset;
res->end = region->end + offset;
}
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pcibios_resource_to_bus);
EXPORT_SYMBOL(pcibios_bus_to_resource);
#endif
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
* addresses to be allocated in the 0x000-0x0ff region
* modulo 0x400.
*
* Why? Because some silly external IO cards only decode
* the low 10 bits of the IO address. The 0x00-0xff region
* is reserved for motherboard devices that decode all 16
* bits, so it's ok to allocate at, say, 0x2800-0x28ff,
* but we want to try to avoid allocating at 0x2900-0x2bff
* which might have be mirrored at 0x0100-0x03ff..
*/
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
struct pci_dev *dev = data;
struct pci_controller *hose = pci_bus_to_host(dev->bus);
unsigned long start = res->start;
unsigned long alignto;
if (res->flags & IORESOURCE_IO) {
unsigned long offset = (unsigned long)hose->io_base_virt -
pci_io_base;
/* Make sure we start at our min on all hoses */
if (start - offset < PCIBIOS_MIN_IO)
start = PCIBIOS_MIN_IO + offset;
/*
* Put everything into 0x00-0xff region modulo 0x400
*/
if (start & 0x300)
start = (start + 0x3ff) & ~0x3ff;
} else if (res->flags & IORESOURCE_MEM) {
/* Make sure we start at our min on all hoses */
if (start - hose->pci_mem_offset < PCIBIOS_MIN_MEM)
start = PCIBIOS_MIN_MEM + hose->pci_mem_offset;
/* Align to multiple of size of minimum base. */
alignto = max(0x1000UL,