~ubuntu-branches/ubuntu/lucid/linux-rt/lucid

« back to all changes in this revision

Viewing changes to arch/sh/drivers/pci/fixups-cayman.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2009-08-05 23:00:52 UTC
  • Revision ID: james.westby@ubuntu.com-20090805230052-7xedvqcyk9dnnxb2
Tags: 2.6.31-1.1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <linux/kernel.h>
 
2
#include <linux/init.h>
 
3
#include <linux/pci.h>
 
4
#include <linux/types.h>
 
5
#include <cpu/irq.h>
 
6
#include "pci-sh5.h"
 
7
 
 
8
int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
9
{
 
10
        int result = -1;
 
11
 
 
12
        /* The complication here is that the PCI IRQ lines from the Cayman's 2
 
13
           5V slots get into the CPU via a different path from the IRQ lines
 
14
           from the 3 3.3V slots.  Thus, we have to detect whether the card's
 
15
           interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
 
16
           at the point where we cross from 5V to 3.3V is not the normal case.
 
17
 
 
18
           The added complication is that we don't know that the 5V slots are
 
19
           always bus 2, because a card containing a PCI-PCI bridge may be
 
20
           plugged into a 3.3V slot, and this changes the bus numbering.
 
21
 
 
22
           Also, the Cayman has an intermediate PCI bus that goes a custom
 
23
           expansion board header (and to the secondary bridge).  This bus has
 
24
           never been used in practice.
 
25
 
 
26
           The 1ary onboard PCI-PCI bridge is device 3 on bus 0
 
27
           The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of
 
28
           the 1ary bridge.
 
29
           */
 
30
 
 
31
        struct slot_pin {
 
32
                int slot;
 
33
                int pin;
 
34
        } path[4];
 
35
        int i=0;
 
36
 
 
37
        while (dev->bus->number > 0) {
 
38
 
 
39
                slot = path[i].slot = PCI_SLOT(dev->devfn);
 
40
                pin = path[i].pin = pci_swizzle_interrupt_pin(dev, pin);
 
41
                dev = dev->bus->self;
 
42
                i++;
 
43
                if (i > 3) panic("PCI path to root bus too long!\n");
 
44
        }
 
45
 
 
46
        slot = PCI_SLOT(dev->devfn);
 
47
        /* This is the slot on bus 0 through which the device is eventually
 
48
           reachable. */
 
49
 
 
50
        /* Now work back up. */
 
51
        if ((slot < 3) || (i == 0)) {
 
52
                /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
 
53
                   swizzle now. */
 
54
                result = IRQ_INTA + pci_swizzle_interrupt_pin(dev, pin) - 1;
 
55
        } else {
 
56
                i--;
 
57
                slot = path[i].slot;
 
58
                pin  = path[i].pin;
 
59
                if (slot > 0) {
 
60
                        panic("PCI expansion bus device found - not handled!\n");
 
61
                } else {
 
62
                        if (i > 0) {
 
63
                                /* 5V slots */
 
64
                                i--;
 
65
                                slot = path[i].slot;
 
66
                                pin  = path[i].pin;
 
67
                                /* 'pin' was swizzled earlier wrt slot, don't do it again. */
 
68
                                result = IRQ_P2INTA + (pin - 1);
 
69
                        } else {
 
70
                                /* IRQ for 2ary PCI-PCI bridge : unused */
 
71
                                result = -1;
 
72
                        }
 
73
                }
 
74
        }
 
75
 
 
76
        return result;
 
77
}