Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-drm-fsl-dcu.git] / arch / ia64 / sn / kernel / io_acpi_init.c
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) 2006 Silicon Graphics, Inc. All rights reserved.
7  */
8
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>
16 #include <linux/slab.h>
17 #include <linux/export.h>
18
19
20 /*
21  * The code in this file will only be executed when running with
22  * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
23  */
24
25
26 /*
27  * This value must match the UUID the PROM uses
28  * (io/acpi/defblk.c) when building a vendor descriptor.
29  */
30 struct acpi_vendor_uuid sn_uuid = {
31         .subtype = 0,
32         .data   = { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
33                     0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
34 };
35
36 struct sn_pcidev_match {
37         u8 bus;
38         unsigned int devfn;
39         acpi_handle handle;
40 };
41
42 /*
43  * Perform the early IO init in PROM.
44  */
45 static long
46 sal_ioif_init(u64 *result)
47 {
48         struct ia64_sal_retval isrv = {0,0,0,0};
49
50         SAL_CALL_NOLOCK(isrv,
51                         SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
52         *result = isrv.v0;
53         return isrv.status;
54 }
55
56 /*
57  * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback()
58  *                         for all SGIHUB and SGITIO acpi devices defined in the
59  *                         DSDT. It obtains the hubdev_info pointer from the
60  *                         ACPI vendor resource, which the PROM setup, and sets up the
61  *                         hubdev_info in the pda.
62  */
63
64 static acpi_status __init
65 sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
66 {
67         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
68         struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
69         u64 addr;
70         struct hubdev_info *hubdev;
71         struct hubdev_info *hubdev_ptr;
72         int i;
73         u64 nasid;
74         struct acpi_resource *resource;
75         acpi_status status;
76         struct acpi_resource_vendor_typed *vendor;
77         extern void sn_common_hubdev_init(struct hubdev_info *);
78
79         status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
80                                           &sn_uuid, &buffer);
81         if (ACPI_FAILURE(status)) {
82                 acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
83                 printk(KERN_ERR
84                        "sn_acpi_hubdev_init: acpi_get_vendor_resource() "
85                        "(0x%x) failed for: %s\n", status,
86                         (char *)name_buffer.pointer);
87                 kfree(name_buffer.pointer);
88                 return AE_OK;           /* Continue walking namespace */
89         }
90
91         resource = buffer.pointer;
92         vendor = &resource->data.vendor_typed;
93         if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
94             sizeof(struct hubdev_info *)) {
95                 acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
96                 printk(KERN_ERR
97                        "sn_acpi_hubdev_init: Invalid vendor data length: "
98                        "%d for: %s\n",
99                         vendor->byte_length, (char *)name_buffer.pointer);
100                 kfree(name_buffer.pointer);
101                 goto exit;
102         }
103
104         memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
105         hubdev_ptr = __va((struct hubdev_info *) addr);
106
107         nasid = hubdev_ptr->hdi_nasid;
108         i = nasid_to_cnodeid(nasid);
109         hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
110         *hubdev = *hubdev_ptr;
111         sn_common_hubdev_init(hubdev);
112
113 exit:
114         kfree(buffer.pointer);
115         return AE_OK;           /* Continue walking namespace */
116 }
117
118 /*
119  * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
120  *                        the ACPI Vendor resource for this bus.
121  */
122 static struct pcibus_bussoft *
123 sn_get_bussoft_ptr(struct pci_bus *bus)
124 {
125         u64 addr;
126         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
127         struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
128         acpi_handle handle;
129         struct pcibus_bussoft *prom_bussoft_ptr;
130         struct acpi_resource *resource;
131         acpi_status status;
132         struct acpi_resource_vendor_typed *vendor;
133
134
135         handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
136         status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
137                                           &sn_uuid, &buffer);
138         if (ACPI_FAILURE(status)) {
139                 acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
140                 printk(KERN_ERR "%s: "
141                        "acpi_get_vendor_resource() failed (0x%x) for: %s\n",
142                        __func__, status, (char *)name_buffer.pointer);
143                 kfree(name_buffer.pointer);
144                 return NULL;
145         }
146         resource = buffer.pointer;
147         vendor = &resource->data.vendor_typed;
148
149         if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
150              sizeof(struct pcibus_bussoft *)) {
151                 printk(KERN_ERR
152                        "%s: Invalid vendor data length %d\n",
153                         __func__, vendor->byte_length);
154                 kfree(buffer.pointer);
155                 return NULL;
156         }
157         memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
158         prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
159         kfree(buffer.pointer);
160
161         return prom_bussoft_ptr;
162 }
163
164 /*
165  * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
166  *                          pointers from the vendor resource using the
167  *                          provided acpi handle, and copy the structures
168  *                          into the argument buffers.
169  */
170 static int
171 sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
172                     struct sn_irq_info **sn_irq_info)
173 {
174         u64 addr;
175         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
176         struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
177         struct sn_irq_info *irq_info, *irq_info_prom;
178         struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
179         struct acpi_resource *resource;
180         int ret = 0;
181         acpi_status status;
182         struct acpi_resource_vendor_typed *vendor;
183
184         /*
185          * The pointer to this device's pcidev_info structure in
186          * the PROM, is in the vendor resource.
187          */
188         status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
189                                           &sn_uuid, &buffer);
190         if (ACPI_FAILURE(status)) {
191                 acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
192                 printk(KERN_ERR
193                        "%s: acpi_get_vendor_resource() failed (0x%x) for: %s\n",
194                         __func__, status, (char *)name_buffer.pointer);
195                 kfree(name_buffer.pointer);
196                 return 1;
197         }
198
199         resource = buffer.pointer;
200         vendor = &resource->data.vendor_typed;
201         if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
202             sizeof(struct pci_devdev_info *)) {
203                 acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
204                 printk(KERN_ERR
205                        "%s: Invalid vendor data length: %d for: %s\n",
206                          __func__, vendor->byte_length,
207                         (char *)name_buffer.pointer);
208                 kfree(name_buffer.pointer);
209                 ret = 1;
210                 goto exit;
211         }
212
213         pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
214         if (!pcidev_ptr)
215                 panic("%s: Unable to alloc memory for pcidev_info", __func__);
216
217         memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *));
218         pcidev_prom_ptr = __va(addr);
219         memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info));
220
221         /* Get the IRQ info */
222         irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
223         if (!irq_info)
224                  panic("%s: Unable to alloc memory for sn_irq_info", __func__);
225
226         if (pcidev_ptr->pdi_sn_irq_info) {
227                 irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info);
228                 memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info));
229         }
230
231         *pcidev_info = pcidev_ptr;
232         *sn_irq_info = irq_info;
233
234 exit:
235         kfree(buffer.pointer);
236         return ret;
237 }
238
239 static unsigned int
240 get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
241 {
242         unsigned long long adr;
243         acpi_handle child;
244         unsigned int devfn;
245         int function;
246         acpi_handle parent;
247         int slot;
248         acpi_status status;
249         struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
250
251         acpi_get_name(device_handle, ACPI_FULL_PATHNAME, &name_buffer);
252
253         /*
254          * Do an upward search to find the root bus device, and
255          * obtain the host devfn from the previous child device.
256          */
257         child = device_handle;
258         while (child) {
259                 status = acpi_get_parent(child, &parent);
260                 if (ACPI_FAILURE(status)) {
261                         printk(KERN_ERR "%s: acpi_get_parent() failed "
262                                "(0x%x) for: %s\n", __func__, status,
263                                 (char *)name_buffer.pointer);
264                         panic("%s: Unable to find host devfn\n", __func__);
265                 }
266                 if (parent == rootbus_handle)
267                         break;
268                 child = parent;
269         }
270         if (!child) {
271                 printk(KERN_ERR "%s: Unable to find root bus for: %s\n",
272                        __func__, (char *)name_buffer.pointer);
273                 BUG();
274         }
275
276         status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
277         if (ACPI_FAILURE(status)) {
278                 printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: %s\n",
279                        __func__, status, (char *)name_buffer.pointer);
280                 panic("%s: Unable to find host devfn\n", __func__);
281         }
282
283         kfree(name_buffer.pointer);
284
285         slot = (adr >> 16) & 0xffff;
286         function = adr & 0xffff;
287         devfn = PCI_DEVFN(slot, function);
288         return devfn;
289 }
290
291 /*
292  * find_matching_device - Callback routine to find the ACPI device
293  *                        that matches up with our pci_dev device.
294  *                        Matching is done on bus number and devfn.
295  *                        To find the bus number for a particular
296  *                        ACPI device, we must look at the _BBN method
297  *                        of its parent.
298  */
299 static acpi_status
300 find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
301 {
302         unsigned long long bbn = -1;
303         unsigned long long adr;
304         acpi_handle parent = NULL;
305         acpi_status status;
306         unsigned int devfn;
307         int function;
308         int slot;
309         struct sn_pcidev_match *info = context;
310         struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
311
312         status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
313                                        &adr);
314         if (ACPI_SUCCESS(status)) {
315                 status = acpi_get_parent(handle, &parent);
316                 if (ACPI_FAILURE(status)) {
317                         acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
318                         printk(KERN_ERR
319                                "%s: acpi_get_parent() failed (0x%x) for: %s\n",
320                                 __func__, status, (char *)name_buffer.pointer);
321                         kfree(name_buffer.pointer);
322                         return AE_OK;
323                 }
324                 status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
325                                                NULL, &bbn);
326                 if (ACPI_FAILURE(status)) {
327                         acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
328                         printk(KERN_ERR
329                           "%s: Failed to find _BBN in parent of: %s\n",
330                                         __func__, (char *)name_buffer.pointer);
331                         kfree(name_buffer.pointer);
332                         return AE_OK;
333                 }
334
335                 slot = (adr >> 16) & 0xffff;
336                 function = adr & 0xffff;
337                 devfn = PCI_DEVFN(slot, function);
338                 if ((info->devfn == devfn) && (info->bus == bbn)) {
339                         /* We have a match! */
340                         info->handle = handle;
341                         return 1;
342                 }
343         }
344         return AE_OK;
345 }
346
347 /*
348  * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
349  *                           device matching the specified pci_dev,
350  *                           and return the pcidev info and irq info.
351  */
352 int
353 sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
354                         struct sn_irq_info **sn_irq_info)
355 {
356         unsigned int host_devfn;
357         struct sn_pcidev_match pcidev_match;
358         acpi_handle rootbus_handle;
359         unsigned long long segment;
360         acpi_status status;
361         struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
362
363         rootbus_handle = acpi_device_handle(PCI_CONTROLLER(dev)->companion);
364         status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
365                                        &segment);
366         if (ACPI_SUCCESS(status)) {
367                 if (segment != pci_domain_nr(dev)) {
368                         acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME,
369                                 &name_buffer);
370                         printk(KERN_ERR
371                                "%s: Segment number mismatch, 0x%llx vs 0x%x for: %s\n",
372                                __func__, segment, pci_domain_nr(dev),
373                                (char *)name_buffer.pointer);
374                         kfree(name_buffer.pointer);
375                         return 1;
376                 }
377         } else {
378                 acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME, &name_buffer);
379                 printk(KERN_ERR "%s: Unable to get __SEG from: %s\n",
380                        __func__, (char *)name_buffer.pointer);
381                 kfree(name_buffer.pointer);
382                 return 1;
383         }
384
385         /*
386          * We want to search all devices in this segment/domain
387          * of the ACPI namespace for the matching ACPI device,
388          * which holds the pcidev_info pointer in its vendor resource.
389          */
390         pcidev_match.bus = dev->bus->number;
391         pcidev_match.devfn = dev->devfn;
392         pcidev_match.handle = NULL;
393
394         acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
395                             find_matching_device, NULL, &pcidev_match, NULL);
396
397         if (!pcidev_match.handle) {
398                 printk(KERN_ERR
399                        "%s: Could not find matching ACPI device for %s.\n",
400                        __func__, pci_name(dev));
401                 return 1;
402         }
403
404         if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
405                 return 1;
406
407         /* Build up the pcidev_info.pdi_slot_host_handle */
408         host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle);
409         (*pcidev_info)->pdi_slot_host_handle =
410                         ((unsigned long) pci_domain_nr(dev) << 40) |
411                                         /* bus == 0 */
412                                         host_devfn;
413         return 0;
414 }
415
416 /*
417  * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
418  *                      Perform any SN specific slot fixup.
419  *                      At present there does not appear to be
420  *                      any generic way to handle a ROM image
421  *                      that has been shadowed by the PROM, so
422  *                      we pass a pointer to it within the
423  *                      pcidev_info structure.
424  */
425
426 void
427 sn_acpi_slot_fixup(struct pci_dev *dev)
428 {
429         void __iomem *addr;
430         struct pcidev_info *pcidev_info = NULL;
431         struct sn_irq_info *sn_irq_info = NULL;
432         size_t image_size, size;
433
434         if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
435                 panic("%s:  Failure obtaining pcidev_info for %s\n",
436                       __func__, pci_name(dev));
437         }
438
439         if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
440                 /*
441                  * A valid ROM image exists and has been shadowed by the
442                  * PROM. Setup the pci_dev ROM resource with the address
443                  * of the shadowed copy, and the actual length of the ROM image.
444                  */
445                 size = pci_resource_len(dev, PCI_ROM_RESOURCE);
446                 addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
447                                size);
448                 image_size = pci_get_rom_size(dev, addr, size);
449                 dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
450                 dev->resource[PCI_ROM_RESOURCE].end =
451                                         (unsigned long) addr + image_size - 1;
452                 dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
453         }
454         sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
455 }
456
457 EXPORT_SYMBOL(sn_acpi_slot_fixup);
458
459
460 /*
461  * sn_acpi_bus_fixup -  Perform SN specific setup of software structs
462  *                      (pcibus_bussoft, pcidev_info) and hardware
463  *                      registers, for the specified bus and devices under it.
464  */
465 void
466 sn_acpi_bus_fixup(struct pci_bus *bus)
467 {
468         struct pci_dev *pci_dev = NULL;
469         struct pcibus_bussoft *prom_bussoft_ptr;
470
471         if (!bus->parent) {     /* If root bus */
472                 prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
473                 if (prom_bussoft_ptr == NULL) {
474                         printk(KERN_ERR
475                                "%s: 0x%04x:0x%02x Unable to "
476                                "obtain prom_bussoft_ptr\n",
477                                __func__, pci_domain_nr(bus), bus->number);
478                         return;
479                 }
480                 sn_common_bus_fixup(bus, prom_bussoft_ptr);
481         }
482         list_for_each_entry(pci_dev, &bus->devices, bus_list) {
483                 sn_acpi_slot_fixup(pci_dev);
484         }
485 }
486
487 /*
488  * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
489  *                   nodes and root buses in the DSDT. As a result, bus scanning
490  *                   will be initiated by the Linux ACPI code.
491  */
492
493 void __init
494 sn_io_acpi_init(void)
495 {
496         u64 result;
497         long status;
498
499         /* SN Altix does not follow the IOSAPIC IRQ routing model */
500         acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
501
502         /* Setup hubdev_info for all SGIHUB/SGITIO devices */
503         acpi_get_devices("SGIHUB", sn_acpi_hubdev_init, NULL, NULL);
504         acpi_get_devices("SGITIO", sn_acpi_hubdev_init, NULL, NULL);
505
506         status = sal_ioif_init(&result);
507         if (status || result)
508                 panic("sal_ioif_init failed: [%lx] %s\n",
509                       status, ia64_sal_strerror(status));
510 }