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
6 * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
9 #include <asm/sn/types.h>
10 #include <asm/sn/addrs.h>
11 #include <asm/sn/pcidev.h>
12 #include <asm/sn/pcibus_provider_defs.h>
13 #include <asm/sn/sn_sal.h>
14 #include "xtalk/hubdev.h"
15 #include <linux/acpi.h>
19 * The code in this file will only be executed when running with
20 * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
25 * This value must match the UUID the PROM uses
26 * (io/acpi/defblk.c) when building a vendor descriptor.
28 struct acpi_vendor_uuid sn_uuid
= {
30 .data
= { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
31 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
34 struct sn_pcidev_match
{
41 * Perform the early IO init in PROM.
44 sal_ioif_init(u64
*result
)
46 struct ia64_sal_retval isrv
= {0,0,0,0};
49 SN_SAL_IOIF_INIT
, 0, 0, 0, 0, 0, 0, 0);
55 * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback()
56 * for all SGIHUB and SGITIO acpi devices defined in the
57 * DSDT. It obtains the hubdev_info pointer from the
58 * ACPI vendor resource, which the PROM setup, and sets up the
59 * hubdev_info in the pda.
62 static acpi_status __init
63 sn_acpi_hubdev_init(acpi_handle handle
, u32 depth
, void *context
, void **ret
)
65 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
66 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
68 struct hubdev_info
*hubdev
;
69 struct hubdev_info
*hubdev_ptr
;
72 struct acpi_resource
*resource
;
74 struct acpi_resource_vendor_typed
*vendor
;
75 extern void sn_common_hubdev_init(struct hubdev_info
*);
77 status
= acpi_get_vendor_resource(handle
, METHOD_NAME__CRS
,
79 if (ACPI_FAILURE(status
)) {
80 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
82 "sn_acpi_hubdev_init: acpi_get_vendor_resource() "
83 "(0x%x) failed for: %s\n", status
,
84 (char *)name_buffer
.pointer
);
85 kfree(name_buffer
.pointer
);
86 return AE_OK
; /* Continue walking namespace */
89 resource
= buffer
.pointer
;
90 vendor
= &resource
->data
.vendor_typed
;
91 if ((vendor
->byte_length
- sizeof(struct acpi_vendor_uuid
)) !=
92 sizeof(struct hubdev_info
*)) {
93 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
95 "sn_acpi_hubdev_init: Invalid vendor data length: "
97 vendor
->byte_length
, (char *)name_buffer
.pointer
);
98 kfree(name_buffer
.pointer
);
102 memcpy(&addr
, vendor
->byte_data
, sizeof(struct hubdev_info
*));
103 hubdev_ptr
= __va((struct hubdev_info
*) addr
);
105 nasid
= hubdev_ptr
->hdi_nasid
;
106 i
= nasid_to_cnodeid(nasid
);
107 hubdev
= (struct hubdev_info
*)(NODEPDA(i
)->pdinfo
);
108 *hubdev
= *hubdev_ptr
;
109 sn_common_hubdev_init(hubdev
);
112 kfree(buffer
.pointer
);
113 return AE_OK
; /* Continue walking namespace */
117 * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
118 * the ACPI Vendor resource for this bus.
120 static struct pcibus_bussoft
*
121 sn_get_bussoft_ptr(struct pci_bus
*bus
)
124 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
125 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
127 struct pcibus_bussoft
*prom_bussoft_ptr
;
128 struct acpi_resource
*resource
;
130 struct acpi_resource_vendor_typed
*vendor
;
133 handle
= PCI_CONTROLLER(bus
)->acpi_handle
;
134 status
= acpi_get_vendor_resource(handle
, METHOD_NAME__CRS
,
136 if (ACPI_FAILURE(status
)) {
137 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
138 printk(KERN_ERR
"%s: "
139 "acpi_get_vendor_resource() failed (0x%x) for: %s\n",
140 __func__
, status
, (char *)name_buffer
.pointer
);
141 kfree(name_buffer
.pointer
);
144 resource
= buffer
.pointer
;
145 vendor
= &resource
->data
.vendor_typed
;
147 if ((vendor
->byte_length
- sizeof(struct acpi_vendor_uuid
)) !=
148 sizeof(struct pcibus_bussoft
*)) {
150 "%s: Invalid vendor data length %d\n",
151 __func__
, vendor
->byte_length
);
152 kfree(buffer
.pointer
);
155 memcpy(&addr
, vendor
->byte_data
, sizeof(struct pcibus_bussoft
*));
156 prom_bussoft_ptr
= __va((struct pcibus_bussoft
*) addr
);
157 kfree(buffer
.pointer
);
159 return prom_bussoft_ptr
;
163 * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
164 * pointers from the vendor resource using the
165 * provided acpi handle, and copy the structures
166 * into the argument buffers.
169 sn_extract_device_info(acpi_handle handle
, struct pcidev_info
**pcidev_info
,
170 struct sn_irq_info
**sn_irq_info
)
173 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
174 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
175 struct sn_irq_info
*irq_info
, *irq_info_prom
;
176 struct pcidev_info
*pcidev_ptr
, *pcidev_prom_ptr
;
177 struct acpi_resource
*resource
;
180 struct acpi_resource_vendor_typed
*vendor
;
183 * The pointer to this device's pcidev_info structure in
184 * the PROM, is in the vendor resource.
186 status
= acpi_get_vendor_resource(handle
, METHOD_NAME__CRS
,
188 if (ACPI_FAILURE(status
)) {
189 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
191 "%s: acpi_get_vendor_resource() failed (0x%x) for: %s\n",
192 __func__
, status
, (char *)name_buffer
.pointer
);
193 kfree(name_buffer
.pointer
);
197 resource
= buffer
.pointer
;
198 vendor
= &resource
->data
.vendor_typed
;
199 if ((vendor
->byte_length
- sizeof(struct acpi_vendor_uuid
)) !=
200 sizeof(struct pci_devdev_info
*)) {
201 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
203 "%s: Invalid vendor data length: %d for: %s\n",
204 __func__
, vendor
->byte_length
,
205 (char *)name_buffer
.pointer
);
206 kfree(name_buffer
.pointer
);
211 pcidev_ptr
= kzalloc(sizeof(struct pcidev_info
), GFP_KERNEL
);
213 panic("%s: Unable to alloc memory for pcidev_info", __func__
);
215 memcpy(&addr
, vendor
->byte_data
, sizeof(struct pcidev_info
*));
216 pcidev_prom_ptr
= __va(addr
);
217 memcpy(pcidev_ptr
, pcidev_prom_ptr
, sizeof(struct pcidev_info
));
219 /* Get the IRQ info */
220 irq_info
= kzalloc(sizeof(struct sn_irq_info
), GFP_KERNEL
);
222 panic("%s: Unable to alloc memory for sn_irq_info", __func__
);
224 if (pcidev_ptr
->pdi_sn_irq_info
) {
225 irq_info_prom
= __va(pcidev_ptr
->pdi_sn_irq_info
);
226 memcpy(irq_info
, irq_info_prom
, sizeof(struct sn_irq_info
));
229 *pcidev_info
= pcidev_ptr
;
230 *sn_irq_info
= irq_info
;
233 kfree(buffer
.pointer
);
238 get_host_devfn(acpi_handle device_handle
, acpi_handle rootbus_handle
)
240 unsigned long long adr
;
247 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
249 acpi_get_name(device_handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
252 * Do an upward search to find the root bus device, and
253 * obtain the host devfn from the previous child device.
255 child
= device_handle
;
257 status
= acpi_get_parent(child
, &parent
);
258 if (ACPI_FAILURE(status
)) {
259 printk(KERN_ERR
"%s: acpi_get_parent() failed "
260 "(0x%x) for: %s\n", __func__
, status
,
261 (char *)name_buffer
.pointer
);
262 panic("%s: Unable to find host devfn\n", __func__
);
264 if (parent
== rootbus_handle
)
269 printk(KERN_ERR
"%s: Unable to find root bus for: %s\n",
270 __func__
, (char *)name_buffer
.pointer
);
274 status
= acpi_evaluate_integer(child
, METHOD_NAME__ADR
, NULL
, &adr
);
275 if (ACPI_FAILURE(status
)) {
276 printk(KERN_ERR
"%s: Unable to get _ADR (0x%x) for: %s\n",
277 __func__
, status
, (char *)name_buffer
.pointer
);
278 panic("%s: Unable to find host devfn\n", __func__
);
281 kfree(name_buffer
.pointer
);
283 slot
= (adr
>> 16) & 0xffff;
284 function
= adr
& 0xffff;
285 devfn
= PCI_DEVFN(slot
, function
);
290 * find_matching_device - Callback routine to find the ACPI device
291 * that matches up with our pci_dev device.
292 * Matching is done on bus number and devfn.
293 * To find the bus number for a particular
294 * ACPI device, we must look at the _BBN method
298 find_matching_device(acpi_handle handle
, u32 lvl
, void *context
, void **rv
)
300 unsigned long long bbn
= -1;
301 unsigned long long adr
;
302 acpi_handle parent
= NULL
;
307 struct sn_pcidev_match
*info
= context
;
308 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
310 status
= acpi_evaluate_integer(handle
, METHOD_NAME__ADR
, NULL
,
312 if (ACPI_SUCCESS(status
)) {
313 status
= acpi_get_parent(handle
, &parent
);
314 if (ACPI_FAILURE(status
)) {
315 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
317 "%s: acpi_get_parent() failed (0x%x) for: %s\n",
318 __func__
, status
, (char *)name_buffer
.pointer
);
319 kfree(name_buffer
.pointer
);
322 status
= acpi_evaluate_integer(parent
, METHOD_NAME__BBN
,
324 if (ACPI_FAILURE(status
)) {
325 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
327 "%s: Failed to find _BBN in parent of: %s\n",
328 __func__
, (char *)name_buffer
.pointer
);
329 kfree(name_buffer
.pointer
);
333 slot
= (adr
>> 16) & 0xffff;
334 function
= adr
& 0xffff;
335 devfn
= PCI_DEVFN(slot
, function
);
336 if ((info
->devfn
== devfn
) && (info
->bus
== bbn
)) {
337 /* We have a match! */
338 info
->handle
= handle
;
346 * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
347 * device matching the specified pci_dev,
348 * and return the pcidev info and irq info.
351 sn_acpi_get_pcidev_info(struct pci_dev
*dev
, struct pcidev_info
**pcidev_info
,
352 struct sn_irq_info
**sn_irq_info
)
354 unsigned int host_devfn
;
355 struct sn_pcidev_match pcidev_match
;
356 acpi_handle rootbus_handle
;
357 unsigned long long segment
;
359 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
361 rootbus_handle
= PCI_CONTROLLER(dev
)->acpi_handle
;
362 status
= acpi_evaluate_integer(rootbus_handle
, METHOD_NAME__SEG
, NULL
,
364 if (ACPI_SUCCESS(status
)) {
365 if (segment
!= pci_domain_nr(dev
)) {
366 acpi_get_name(rootbus_handle
, ACPI_FULL_PATHNAME
,
369 "%s: Segment number mismatch, 0x%llx vs 0x%x for: %s\n",
370 __func__
, segment
, pci_domain_nr(dev
),
371 (char *)name_buffer
.pointer
);
372 kfree(name_buffer
.pointer
);
376 acpi_get_name(rootbus_handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
377 printk(KERN_ERR
"%s: Unable to get __SEG from: %s\n",
378 __func__
, (char *)name_buffer
.pointer
);
379 kfree(name_buffer
.pointer
);
384 * We want to search all devices in this segment/domain
385 * of the ACPI namespace for the matching ACPI device,
386 * which holds the pcidev_info pointer in its vendor resource.
388 pcidev_match
.bus
= dev
->bus
->number
;
389 pcidev_match
.devfn
= dev
->devfn
;
390 pcidev_match
.handle
= NULL
;
392 acpi_walk_namespace(ACPI_TYPE_DEVICE
, rootbus_handle
, ACPI_UINT32_MAX
,
393 find_matching_device
, &pcidev_match
, NULL
);
395 if (!pcidev_match
.handle
) {
397 "%s: Could not find matching ACPI device for %s.\n",
398 __func__
, pci_name(dev
));
402 if (sn_extract_device_info(pcidev_match
.handle
, pcidev_info
, sn_irq_info
))
405 /* Build up the pcidev_info.pdi_slot_host_handle */
406 host_devfn
= get_host_devfn(pcidev_match
.handle
, rootbus_handle
);
407 (*pcidev_info
)->pdi_slot_host_handle
=
408 ((unsigned long) pci_domain_nr(dev
) << 40) |
415 * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
416 * Perform any SN specific slot fixup.
417 * At present there does not appear to be
418 * any generic way to handle a ROM image
419 * that has been shadowed by the PROM, so
420 * we pass a pointer to it within the
421 * pcidev_info structure.
425 sn_acpi_slot_fixup(struct pci_dev
*dev
)
428 struct pcidev_info
*pcidev_info
= NULL
;
429 struct sn_irq_info
*sn_irq_info
= NULL
;
430 size_t image_size
, size
;
432 if (sn_acpi_get_pcidev_info(dev
, &pcidev_info
, &sn_irq_info
)) {
433 panic("%s: Failure obtaining pcidev_info for %s\n",
434 __func__
, pci_name(dev
));
437 if (pcidev_info
->pdi_pio_mapped_addr
[PCI_ROM_RESOURCE
]) {
439 * A valid ROM image exists and has been shadowed by the
440 * PROM. Setup the pci_dev ROM resource with the address
441 * of the shadowed copy, and the actual length of the ROM image.
443 size
= pci_resource_len(dev
, PCI_ROM_RESOURCE
);
444 addr
= ioremap(pcidev_info
->pdi_pio_mapped_addr
[PCI_ROM_RESOURCE
],
446 image_size
= pci_get_rom_size(dev
, addr
, size
);
447 dev
->resource
[PCI_ROM_RESOURCE
].start
= (unsigned long) addr
;
448 dev
->resource
[PCI_ROM_RESOURCE
].end
=
449 (unsigned long) addr
+ image_size
- 1;
450 dev
->resource
[PCI_ROM_RESOURCE
].flags
|= IORESOURCE_ROM_BIOS_COPY
;
452 sn_pci_fixup_slot(dev
, pcidev_info
, sn_irq_info
);
455 EXPORT_SYMBOL(sn_acpi_slot_fixup
);
459 * sn_acpi_bus_fixup - Perform SN specific setup of software structs
460 * (pcibus_bussoft, pcidev_info) and hardware
461 * registers, for the specified bus and devices under it.
464 sn_acpi_bus_fixup(struct pci_bus
*bus
)
466 struct pci_dev
*pci_dev
= NULL
;
467 struct pcibus_bussoft
*prom_bussoft_ptr
;
469 if (!bus
->parent
) { /* If root bus */
470 prom_bussoft_ptr
= sn_get_bussoft_ptr(bus
);
471 if (prom_bussoft_ptr
== NULL
) {
473 "%s: 0x%04x:0x%02x Unable to "
474 "obtain prom_bussoft_ptr\n",
475 __func__
, pci_domain_nr(bus
), bus
->number
);
478 sn_common_bus_fixup(bus
, prom_bussoft_ptr
);
480 list_for_each_entry(pci_dev
, &bus
->devices
, bus_list
) {
481 sn_acpi_slot_fixup(pci_dev
);
486 * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
487 * nodes and root buses in the DSDT. As a result, bus scanning
488 * will be initiated by the Linux ACPI code.
492 sn_io_acpi_init(void)
497 /* SN Altix does not follow the IOSAPIC IRQ routing model */
498 acpi_irq_model
= ACPI_IRQ_MODEL_PLATFORM
;
500 /* Setup hubdev_info for all SGIHUB/SGITIO devices */
501 acpi_get_devices("SGIHUB", sn_acpi_hubdev_init
, NULL
, NULL
);
502 acpi_get_devices("SGITIO", sn_acpi_hubdev_init
, NULL
, NULL
);
504 status
= sal_ioif_init(&result
);
505 if (status
|| result
)
506 panic("sal_ioif_init failed: [%lx] %s\n",
507 status
, ia64_sal_strerror(status
));