diff options
author | Paul Mundt <lethal@linux-sh.org> | 2007-11-22 02:29:10 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-01-27 23:18:55 -0500 |
commit | b6d7b666097e79a8908e3c43fd55fd291a95e133 (patch) | |
tree | 61ab633feecd144d129fc3b220ecb9376c7949bd /arch/sh/drivers/pci/ops-cayman.c | |
parent | d5f68c6dbda8e63df258a0c639f03d7565cf1d50 (diff) |
sh: Get the SH-5 PCI support building.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/drivers/pci/ops-cayman.c')
-rw-r--r-- | arch/sh/drivers/pci/ops-cayman.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/arch/sh/drivers/pci/ops-cayman.c b/arch/sh/drivers/pci/ops-cayman.c new file mode 100644 index 000000000000..980275ffa30b --- /dev/null +++ b/arch/sh/drivers/pci/ops-cayman.c | |||
@@ -0,0 +1,94 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/pci.h> | ||
4 | #include <linux/types.h> | ||
5 | #include <asm/cpu/irq.h> | ||
6 | #include "pci-sh5.h" | ||
7 | |||
8 | static inline u8 bridge_swizzle(u8 pin, u8 slot) | ||
9 | { | ||
10 | return (((pin - 1) + slot) % 4) + 1; | ||
11 | } | ||
12 | |||
13 | int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
14 | { | ||
15 | int result = -1; | ||
16 | |||
17 | /* The complication here is that the PCI IRQ lines from the Cayman's 2 | ||
18 | 5V slots get into the CPU via a different path from the IRQ lines | ||
19 | from the 3 3.3V slots. Thus, we have to detect whether the card's | ||
20 | interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling' | ||
21 | at the point where we cross from 5V to 3.3V is not the normal case. | ||
22 | |||
23 | The added complication is that we don't know that the 5V slots are | ||
24 | always bus 2, because a card containing a PCI-PCI bridge may be | ||
25 | plugged into a 3.3V slot, and this changes the bus numbering. | ||
26 | |||
27 | Also, the Cayman has an intermediate PCI bus that goes a custom | ||
28 | expansion board header (and to the secondary bridge). This bus has | ||
29 | never been used in practice. | ||
30 | |||
31 | The 1ary onboard PCI-PCI bridge is device 3 on bus 0 | ||
32 | The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of | ||
33 | the 1ary bridge. | ||
34 | */ | ||
35 | |||
36 | struct slot_pin { | ||
37 | int slot; | ||
38 | int pin; | ||
39 | } path[4]; | ||
40 | int i=0; | ||
41 | |||
42 | while (dev->bus->number > 0) { | ||
43 | |||
44 | slot = path[i].slot = PCI_SLOT(dev->devfn); | ||
45 | pin = path[i].pin = bridge_swizzle(pin, slot); | ||
46 | dev = dev->bus->self; | ||
47 | i++; | ||
48 | if (i > 3) panic("PCI path to root bus too long!\n"); | ||
49 | } | ||
50 | |||
51 | slot = PCI_SLOT(dev->devfn); | ||
52 | /* This is the slot on bus 0 through which the device is eventually | ||
53 | reachable. */ | ||
54 | |||
55 | /* Now work back up. */ | ||
56 | if ((slot < 3) || (i == 0)) { | ||
57 | /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final | ||
58 | swizzle now. */ | ||
59 | result = IRQ_INTA + bridge_swizzle(pin, slot) - 1; | ||
60 | } else { | ||
61 | i--; | ||
62 | slot = path[i].slot; | ||
63 | pin = path[i].pin; | ||
64 | if (slot > 0) { | ||
65 | panic("PCI expansion bus device found - not handled!\n"); | ||
66 | } else { | ||
67 | if (i > 0) { | ||
68 | /* 5V slots */ | ||
69 | i--; | ||
70 | slot = path[i].slot; | ||
71 | pin = path[i].pin; | ||
72 | /* 'pin' was swizzled earlier wrt slot, don't do it again. */ | ||
73 | result = IRQ_P2INTA + (pin - 1); | ||
74 | } else { | ||
75 | /* IRQ for 2ary PCI-PCI bridge : unused */ | ||
76 | result = -1; | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return result; | ||
82 | } | ||
83 | |||
84 | struct pci_channel board_pci_channels[] = { | ||
85 | { &sh5_pci_ops, NULL, NULL, 0, 0xff }, | ||
86 | { NULL, NULL, NULL, 0, 0 }, | ||
87 | }; | ||
88 | EXPORT_SYMBOL(board_pci_channels); | ||
89 | |||
90 | int __init pcibios_init_platform(void) | ||
91 | { | ||
92 | return sh5pci_init(__pa(memory_start), | ||
93 | __pa(memory_end) - __pa(memory_start)); | ||
94 | } | ||