1/* ASB2305 PCI resource stuff 2 * 3 * Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * - Derived from arch/i386/pci-i386.c 6 * - Copyright 1997--2000 Martin Mares <mj@suse.cz> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public Licence 10 * as published by the Free Software Foundation; either version 11 * 2 of the Licence, or (at your option) any later version. 12 */ 13#include <linux/types.h> 14#include <linux/kernel.h> 15#include <linux/pci.h> 16#include <linux/init.h> 17#include <linux/ioport.h> 18#include <linux/errno.h> 19#include "pci-asb2305.h" 20 21/* 22 * We need to avoid collisions with `mirrored' VGA ports 23 * and other strange ISA hardware, so we always want the 24 * addresses to be allocated in the 0x000-0x0ff region 25 * modulo 0x400. 26 * 27 * Why? Because some silly external IO cards only decode 28 * the low 10 bits of the IO address. The 0x00-0xff region 29 * is reserved for motherboard devices that decode all 16 30 * bits, so it's ok to allocate at, say, 0x2800-0x28ff, 31 * but we want to try to avoid allocating at 0x2900-0x2bff 32 * which might have be mirrored at 0x0100-0x03ff.. 33 */ 34resource_size_t pcibios_align_resource(void *data, const struct resource *res, 35 resource_size_t size, resource_size_t align) 36{ 37 resource_size_t start = res->start; 38 39 40 if ((res->flags & IORESOURCE_IO) && (start & 0x300)) 41 start = (start + 0x3ff) & ~0x3ff; 42 43 return start; 44} 45 46 47static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) 48{ 49 struct pci_bus *bus; 50 struct pci_dev *dev; 51 int idx; 52 struct resource *r, *pr; 53 54 /* Depth-First Search on bus tree */ 55 list_for_each_entry(bus, bus_list, node) { 56 dev = bus->self; 57 if (dev) { 58 for (idx = PCI_BRIDGE_RESOURCES; 59 idx < PCI_NUM_RESOURCES; 60 idx++) { 61 r = &dev->resource[idx]; 62 if (!r->flags) 63 continue; 64 pr = pci_find_parent_resource(dev, r); 65 if (!r->start || 66 !pr || 67 request_resource(pr, r) < 0) { 68 printk(KERN_ERR "PCI:" 69 " Cannot allocate resource" 70 " region %d of bridge %s\n", 71 idx, pci_name(dev)); 72 /* Something is wrong with the region. 73 * Invalidate the resource to prevent 74 * child resource allocations in this 75 * range. */ 76 r->start = r->end = 0; 77 r->flags = 0; 78 } 79 } 80 } 81 pcibios_allocate_bus_resources(&bus->children); 82 } 83} 84 85static void __init pcibios_allocate_resources(int pass) 86{ 87 struct pci_dev *dev = NULL; 88 int idx, disabled; 89 u16 command; 90 struct resource *r, *pr; 91 92 for_each_pci_dev(dev) { 93 pci_read_config_word(dev, PCI_COMMAND, &command); 94 for (idx = 0; idx < 6; idx++) { 95 r = &dev->resource[idx]; 96 if (r->parent) /* Already allocated */ 97 continue; 98 if (!r->start) /* Address not assigned */ 99 continue; 100 if (r->flags & IORESOURCE_IO) 101 disabled = !(command & PCI_COMMAND_IO); 102 else 103 disabled = !(command & PCI_COMMAND_MEMORY); 104 if (pass == disabled) { 105 DBG("PCI[%s]: Resource %08lx-%08lx" 106 " (f=%lx, d=%d, p=%d)\n", 107 pci_name(dev), r->start, r->end, r->flags, 108 disabled, pass); 109 pr = pci_find_parent_resource(dev, r); 110 if (!pr || request_resource(pr, r) < 0) { 111 printk(KERN_ERR "PCI:" 112 " Cannot allocate resource" 113 " region %d of device %s\n", 114 idx, pci_name(dev)); 115 /* We'll assign a new address later */ 116 r->end -= r->start; 117 r->start = 0; 118 } 119 } 120 } 121 if (!pass) { 122 r = &dev->resource[PCI_ROM_RESOURCE]; 123 if (r->flags & IORESOURCE_ROM_ENABLE) { 124 /* Turn the ROM off, leave the resource region, 125 * but keep it unregistered. */ 126 u32 reg; 127 DBG("PCI: Switching off ROM of %s\n", 128 pci_name(dev)); 129 r->flags &= ~IORESOURCE_ROM_ENABLE; 130 pci_read_config_dword( 131 dev, dev->rom_base_reg, ®); 132 pci_write_config_dword( 133 dev, dev->rom_base_reg, 134 reg & ~PCI_ROM_ADDRESS_ENABLE); 135 } 136 } 137 } 138} 139 140static int __init pcibios_assign_resources(void) 141{ 142 struct pci_dev *dev = NULL; 143 struct resource *r, *pr; 144 145 if (!(pci_probe & PCI_ASSIGN_ROMS)) { 146 /* Try to use BIOS settings for ROMs, otherwise let 147 pci_assign_unassigned_resources() allocate the new 148 addresses. */ 149 for_each_pci_dev(dev) { 150 r = &dev->resource[PCI_ROM_RESOURCE]; 151 if (!r->flags || !r->start) 152 continue; 153 pr = pci_find_parent_resource(dev, r); 154 if (!pr || request_resource(pr, r) < 0) { 155 r->end -= r->start; 156 r->start = 0; 157 } 158 } 159 } 160 161 pci_assign_unassigned_resources(); 162 163 return 0; 164} 165 166fs_initcall(pcibios_assign_resources); 167 168void __init pcibios_resource_survey(void) 169{ 170 DBG("PCI: Allocating resources\n"); 171 pcibios_allocate_bus_resources(&pci_root_buses); 172 pcibios_allocate_resources(0); 173 pcibios_allocate_resources(1); 174} 175 176/* 177 * If we set up a device for bus mastering, we need to check the latency 178 * timer as certain crappy BIOSes forget to set it properly. 179 */ 180unsigned int pcibios_max_latency = 255; 181 182void pcibios_set_master(struct pci_dev *dev) 183{ 184 u8 lat; 185 186 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); 187 188 if (lat < 16) 189 lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; 190 else if (lat > pcibios_max_latency) 191 lat = pcibios_max_latency; 192 else 193 return; 194 195 pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); 196} 197 198int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, 199 enum pci_mmap_state mmap_state, int write_combine) 200{ 201 unsigned long prot; 202 203 /* Leave vm_pgoff as-is, the PCI space address is the physical 204 * address on this platform. 205 */ 206 vma->vm_flags |= VM_LOCKED | VM_IO; 207 208 prot = pgprot_val(vma->vm_page_prot); 209 prot &= ~_PAGE_CACHE; 210 vma->vm_page_prot = __pgprot(prot); 211 212 /* Write-combine setting is ignored */ 213 if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, 214 vma->vm_end - vma->vm_start, 215 vma->vm_page_prot)) 216 return -EAGAIN; 217 218 return 0; 219} 220