/* pci-frv.c: low-level PCI access routines1*2* Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4* - Derived from the i386 equivalent stuff5*6* This program is free software; you can redistribute it and/or7* modify it under the terms of the GNU General Public License8* as published by the Free Software Foundation; either version9* 2 of the License, or (at your option) any later version.10*/1112#include <linux/types.h>13#include <linux/kernel.h>14#include <linux/pci.h>15#include <linux/init.h>16#include <linux/ioport.h>17#include <linux/errno.h>1819#include "pci-frv.h"2021/*22* We need to avoid collisions with `mirrored' VGA ports23* and other strange ISA hardware, so we always want the24* addresses to be allocated in the 0x000-0x0ff region25* modulo 0x400.26*27* Why? Because some silly external IO cards only decode28* the low 10 bits of the IO address. The 0x00-0xff region29* is reserved for motherboard devices that decode all 1630* bits, so it's ok to allocate at, say, 0x2800-0x28ff,31* but we want to try to avoid allocating at 0x2900-0x2bff32* which might have be mirrored at 0x0100-0x03ff..33*/34resource_size_t35pcibios_align_resource(void *data, const struct resource *res,36resource_size_t size, resource_size_t align)37{38resource_size_t start = res->start;3940if ((res->flags & IORESOURCE_IO) && (start & 0x300))41start = (start + 0x3ff) & ~0x3ff;4243return start;44}454647/*48* Handle resources of PCI devices. If the world were perfect, we could49* just allocate all the resource regions and do nothing more. It isn't.50* On the other hand, we cannot just re-allocate all devices, as it would51* require us to know lots of host bridge internals. So we attempt to52* keep as much of the original configuration as possible, but tweak it53* when it's found to be wrong.54*55* Known BIOS problems we have to work around:56* - I/O or memory regions not configured57* - regions configured, but not enabled in the command register58* - bogus I/O addresses above 64K used59* - expansion ROMs left enabled (this may sound harmless, but given60* the fact the PCI specs explicitly allow address decoders to be61* shared between expansion ROMs and other resource regions, it's62* at least dangerous)63*64* Our solution:65* (1) Allocate resources for all buses behind PCI-to-PCI bridges.66* This gives us fixed barriers on where we can allocate.67* (2) Allocate resources for all enabled devices. If there is68* a collision, just mark the resource as unallocated. Also69* disable expansion ROMs during this step.70* (3) Try to allocate resources for disabled devices. If the71* resources were assigned correctly, everything goes well,72* if they weren't, they won't disturb allocation of other73* resources.74* (4) Assign new addresses to resources which were either75* not configured at all or misconfigured. If explicitly76* requested by the user, configure expansion ROM address77* as well.78*/7980static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)81{82struct list_head *ln;83struct pci_bus *bus;84struct pci_dev *dev;85int idx;86struct resource *r;8788/* Depth-First Search on bus tree */89for (ln=bus_list->next; ln != bus_list; ln=ln->next) {90bus = pci_bus_b(ln);91if ((dev = bus->self)) {92for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {93r = &dev->resource[idx];94if (!r->start)95continue;96pci_claim_resource(dev, idx);97}98}99pcibios_allocate_bus_resources(&bus->children);100}101}102103static void __init pcibios_allocate_resources(int pass)104{105struct pci_dev *dev = NULL;106int idx, disabled;107u16 command;108struct resource *r;109110for_each_pci_dev(dev) {111pci_read_config_word(dev, PCI_COMMAND, &command);112for(idx = 0; idx < 6; idx++) {113r = &dev->resource[idx];114if (r->parent) /* Already allocated */115continue;116if (!r->start) /* Address not assigned at all */117continue;118if (r->flags & IORESOURCE_IO)119disabled = !(command & PCI_COMMAND_IO);120else121disabled = !(command & PCI_COMMAND_MEMORY);122if (pass == disabled) {123DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",124r->start, r->end, r->flags, disabled, pass);125if (pci_claim_resource(dev, idx) < 0) {126/* We'll assign a new address later */127r->end -= r->start;128r->start = 0;129}130}131}132if (!pass) {133r = &dev->resource[PCI_ROM_RESOURCE];134if (r->flags & IORESOURCE_ROM_ENABLE) {135/* Turn the ROM off, leave the resource region, but keep it unregistered. */136u32 reg;137DBG("PCI: Switching off ROM of %s\n", pci_name(dev));138r->flags &= ~IORESOURCE_ROM_ENABLE;139pci_read_config_dword(dev, dev->rom_base_reg, ®);140pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);141}142}143}144}145146static void __init pcibios_assign_resources(void)147{148struct pci_dev *dev = NULL;149int idx;150struct resource *r;151152for_each_pci_dev(dev) {153int class = dev->class >> 8;154155/* Don't touch classless devices and host bridges */156if (!class || class == PCI_CLASS_BRIDGE_HOST)157continue;158159for(idx=0; idx<6; idx++) {160r = &dev->resource[idx];161162/*163* Don't touch IDE controllers and I/O ports of video cards!164*/165if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||166(class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))167continue;168169/*170* We shall assign a new address to this resource, either because171* the BIOS forgot to do so or because we have decided the old172* address was unusable for some reason.173*/174if (!r->start && r->end)175pci_assign_resource(dev, idx);176}177178if (pci_probe & PCI_ASSIGN_ROMS) {179r = &dev->resource[PCI_ROM_RESOURCE];180r->end -= r->start;181r->start = 0;182if (r->end)183pci_assign_resource(dev, PCI_ROM_RESOURCE);184}185}186}187188void __init pcibios_resource_survey(void)189{190DBG("PCI: Allocating resources\n");191pcibios_allocate_bus_resources(&pci_root_buses);192pcibios_allocate_resources(0);193pcibios_allocate_resources(1);194pcibios_assign_resources();195}196197/*198* If we set up a device for bus mastering, we need to check the latency199* timer as certain crappy BIOSes forget to set it properly.200*/201unsigned int pcibios_max_latency = 255;202203void pcibios_set_master(struct pci_dev *dev)204{205u8 lat;206pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);207if (lat < 16)208lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;209else if (lat > pcibios_max_latency)210lat = pcibios_max_latency;211else212return;213printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);214pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);215}216217218