1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved. 7 */ 8 9#include <linux/slab.h> 10#include <linux/export.h> 11#include <asm/sn/types.h> 12#include <asm/sn/addrs.h> 13#include <asm/sn/io.h> 14#include <asm/sn/module.h> 15#include <asm/sn/intr.h> 16#include <asm/sn/pcibus_provider_defs.h> 17#include <asm/sn/pcidev.h> 18#include <asm/sn/sn_sal.h> 19#include "xtalk/hubdev.h" 20 21/* 22 * The code in this file will only be executed when running with 23 * a PROM that does _not_ have base ACPI IO support. 24 * (i.e., SN_ACPI_BASE_SUPPORT() == 0) 25 */ 26 27static int max_segment_number; /* Default highest segment number */ 28static int max_pcibus_number = 255; /* Default highest pci bus number */ 29 30 31/* 32 * Retrieve the hub device info structure for the given nasid. 33 */ 34static inline u64 sal_get_hubdev_info(u64 handle, u64 address) 35{ 36 struct ia64_sal_retval ret_stuff; 37 ret_stuff.status = 0; 38 ret_stuff.v0 = 0; 39 40 SAL_CALL_NOLOCK(ret_stuff, 41 (u64) SN_SAL_IOIF_GET_HUBDEV_INFO, 42 (u64) handle, (u64) address, 0, 0, 0, 0, 0); 43 return ret_stuff.v0; 44} 45 46/* 47 * Retrieve the pci bus information given the bus number. 48 */ 49static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) 50{ 51 struct ia64_sal_retval ret_stuff; 52 ret_stuff.status = 0; 53 ret_stuff.v0 = 0; 54 55 SAL_CALL_NOLOCK(ret_stuff, 56 (u64) SN_SAL_IOIF_GET_PCIBUS_INFO, 57 (u64) segment, (u64) busnum, (u64) address, 0, 0, 0, 0); 58 return ret_stuff.v0; 59} 60 61/* 62 * Retrieve the pci device information given the bus and device|function number. 63 */ 64static inline u64 65sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, 66 u64 sn_irq_info) 67{ 68 struct ia64_sal_retval ret_stuff; 69 ret_stuff.status = 0; 70 ret_stuff.v0 = 0; 71 72 SAL_CALL_NOLOCK(ret_stuff, 73 (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, 74 (u64) segment, (u64) bus_number, (u64) devfn, 75 (u64) pci_dev, 76 sn_irq_info, 0, 0); 77 return ret_stuff.v0; 78} 79 80 81/* 82 * sn_fixup_ionodes() - This routine initializes the HUB data structure for 83 * each node in the system. This function is only 84 * executed when running with a non-ACPI capable PROM. 85 */ 86static void __init sn_fixup_ionodes(void) 87{ 88 89 struct hubdev_info *hubdev; 90 u64 status; 91 u64 nasid; 92 int i; 93 extern void sn_common_hubdev_init(struct hubdev_info *); 94 95 /* 96 * Get SGI Specific HUB chipset information. 97 * Inform Prom that this kernel can support domain bus numbering. 98 */ 99 for (i = 0; i < num_cnodes; i++) { 100 hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo); 101 nasid = cnodeid_to_nasid(i); 102 hubdev->max_segment_number = 0xffffffff; 103 hubdev->max_pcibus_number = 0xff; 104 status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev)); 105 if (status) 106 continue; 107 108 /* Save the largest Domain and pcibus numbers found. */ 109 if (hubdev->max_segment_number) { 110 /* 111 * Dealing with a Prom that supports segments. 112 */ 113 max_segment_number = hubdev->max_segment_number; 114 max_pcibus_number = hubdev->max_pcibus_number; 115 } 116 sn_common_hubdev_init(hubdev); 117 } 118} 119 120/* 121 * sn_pci_legacy_window_fixup - Setup PCI resources for 122 * legacy IO and MEM space. This needs to 123 * be done here, as the PROM does not have 124 * ACPI support defining the root buses 125 * and their resources (_CRS), 126 */ 127static void 128sn_legacy_pci_window_fixup(struct resource *res, 129 u64 legacy_io, u64 legacy_mem) 130{ 131 res[0].name = "legacy_io"; 132 res[0].flags = IORESOURCE_IO; 133 res[0].start = legacy_io; 134 res[0].end = res[0].start + 0xffff; 135 res[0].parent = &ioport_resource; 136 res[1].name = "legacy_mem"; 137 res[1].flags = IORESOURCE_MEM; 138 res[1].start = legacy_mem; 139 res[1].end = res[1].start + (1024 * 1024) - 1; 140 res[1].parent = &iomem_resource; 141} 142 143/* 144 * sn_io_slot_fixup() - We are not running with an ACPI capable PROM, 145 * and need to convert the pci_dev->resource 146 * 'start' and 'end' addresses to mapped addresses, 147 * and setup the pci_controller->window array entries. 148 */ 149void 150sn_io_slot_fixup(struct pci_dev *dev) 151{ 152 int idx; 153 unsigned long addr, end, size, start; 154 struct pcidev_info *pcidev_info; 155 struct sn_irq_info *sn_irq_info; 156 int status; 157 158 pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); 159 if (!pcidev_info) 160 panic("%s: Unable to alloc memory for pcidev_info", __func__); 161 162 sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); 163 if (!sn_irq_info) 164 panic("%s: Unable to alloc memory for sn_irq_info", __func__); 165 166 /* Call to retrieve pci device information needed by kernel. */ 167 status = sal_get_pcidev_info((u64) pci_domain_nr(dev), 168 (u64) dev->bus->number, 169 dev->devfn, 170 (u64) __pa(pcidev_info), 171 (u64) __pa(sn_irq_info)); 172 173 BUG_ON(status); /* Cannot get platform pci device information */ 174 175 176 /* Copy over PIO Mapped Addresses */ 177 for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { 178 179 if (!pcidev_info->pdi_pio_mapped_addr[idx]) { 180 continue; 181 } 182 183 start = dev->resource[idx].start; 184 end = dev->resource[idx].end; 185 size = end - start; 186 if (size == 0) { 187 continue; 188 } 189 addr = pcidev_info->pdi_pio_mapped_addr[idx]; 190 addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; 191 dev->resource[idx].start = addr; 192 dev->resource[idx].end = addr + size; 193 194 /* 195 * if it's already in the device structure, remove it before 196 * inserting 197 */ 198 if (dev->resource[idx].parent && dev->resource[idx].parent->child) 199 release_resource(&dev->resource[idx]); 200 201 if (dev->resource[idx].flags & IORESOURCE_IO) 202 insert_resource(&ioport_resource, &dev->resource[idx]); 203 else 204 insert_resource(&iomem_resource, &dev->resource[idx]); 205 /* 206 * If ROM, set the actual ROM image size, and mark as 207 * shadowed in PROM. 208 */ 209 if (idx == PCI_ROM_RESOURCE) { 210 size_t image_size; 211 void __iomem *rom; 212 213 rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE), 214 size + 1); 215 image_size = pci_get_rom_size(dev, rom, size + 1); 216 dev->resource[PCI_ROM_RESOURCE].end = 217 dev->resource[PCI_ROM_RESOURCE].start + 218 image_size - 1; 219 dev->resource[PCI_ROM_RESOURCE].flags |= 220 IORESOURCE_ROM_BIOS_COPY; 221 } 222 } 223 224 sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); 225} 226 227EXPORT_SYMBOL(sn_io_slot_fixup); 228 229/* 230 * sn_pci_controller_fixup() - This routine sets up a bus's resources 231 * consistent with the Linux PCI abstraction layer. 232 */ 233static void __init 234sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) 235{ 236 s64 status = 0; 237 struct pci_controller *controller; 238 struct pcibus_bussoft *prom_bussoft_ptr; 239 struct resource *res; 240 LIST_HEAD(resources); 241 242 status = sal_get_pcibus_info((u64) segment, (u64) busnum, 243 (u64) ia64_tpa(&prom_bussoft_ptr)); 244 if (status > 0) 245 return; /*bus # does not exist */ 246 prom_bussoft_ptr = __va(prom_bussoft_ptr); 247 248 controller = kzalloc(sizeof(*controller), GFP_KERNEL); 249 BUG_ON(!controller); 250 controller->segment = segment; 251 252 res = kcalloc(2, sizeof(struct resource), GFP_KERNEL); 253 BUG_ON(!res); 254 255 /* 256 * Temporarily save the prom_bussoft_ptr for use by sn_bus_fixup(). 257 * (platform_data will be overwritten later in sn_common_bus_fixup()) 258 */ 259 controller->platform_data = prom_bussoft_ptr; 260 261 sn_legacy_pci_window_fixup(res, 262 prom_bussoft_ptr->bs_legacy_io, 263 prom_bussoft_ptr->bs_legacy_mem); 264 pci_add_resource_offset(&resources, &res[0], 265 prom_bussoft_ptr->bs_legacy_io); 266 pci_add_resource_offset(&resources, &res[1], 267 prom_bussoft_ptr->bs_legacy_mem); 268 269 bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller, 270 &resources); 271 if (bus == NULL) { 272 kfree(res); 273 kfree(controller); 274 return; 275 } 276 pci_bus_add_devices(bus); 277} 278 279/* 280 * sn_bus_fixup 281 */ 282void 283sn_bus_fixup(struct pci_bus *bus) 284{ 285 struct pci_dev *pci_dev = NULL; 286 struct pcibus_bussoft *prom_bussoft_ptr; 287 288 if (!bus->parent) { /* If root bus */ 289 prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data; 290 if (prom_bussoft_ptr == NULL) { 291 printk(KERN_ERR 292 "sn_bus_fixup: 0x%04x:0x%02x Unable to " 293 "obtain prom_bussoft_ptr\n", 294 pci_domain_nr(bus), bus->number); 295 return; 296 } 297 sn_common_bus_fixup(bus, prom_bussoft_ptr); 298 } 299 list_for_each_entry(pci_dev, &bus->devices, bus_list) { 300 sn_io_slot_fixup(pci_dev); 301 } 302 303} 304 305/* 306 * sn_io_init - PROM does not have ACPI support to define nodes or root buses, 307 * so we need to do things the hard way, including initiating the 308 * bus scanning ourselves. 309 */ 310 311void __init sn_io_init(void) 312{ 313 int i, j; 314 315 sn_fixup_ionodes(); 316 317 /* busses are not known yet ... */ 318 for (i = 0; i <= max_segment_number; i++) 319 for (j = 0; j <= max_pcibus_number; j++) 320 sn_pci_controller_fixup(i, j, NULL); 321} 322