diff options
Diffstat (limited to 'arch/powerpc/sysdev/indirect_pci.c')
-rw-r--r-- | arch/powerpc/sysdev/indirect_pci.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c index c7e6e859b393..a8ac2dfdd3d4 100644 --- a/arch/powerpc/sysdev/indirect_pci.c +++ b/arch/powerpc/sysdev/indirect_pci.c | |||
@@ -20,12 +20,6 @@ | |||
20 | #include <asm/pci-bridge.h> | 20 | #include <asm/pci-bridge.h> |
21 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
22 | 22 | ||
23 | #ifdef CONFIG_PPC_INDIRECT_PCI_BE | ||
24 | #define PCI_CFG_OUT out_be32 | ||
25 | #else | ||
26 | #define PCI_CFG_OUT out_le32 | ||
27 | #endif | ||
28 | |||
29 | static int | 23 | static int |
30 | indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | 24 | indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, |
31 | int len, u32 *val) | 25 | int len, u32 *val) |
@@ -35,10 +29,17 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
35 | u8 cfg_type = 0; | 29 | u8 cfg_type = 0; |
36 | u32 bus_no, reg; | 30 | u32 bus_no, reg; |
37 | 31 | ||
32 | if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) { | ||
33 | if (bus->number != hose->first_busno) | ||
34 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
35 | if (devfn != 0) | ||
36 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
37 | } | ||
38 | |||
38 | if (ppc_md.pci_exclude_device) | 39 | if (ppc_md.pci_exclude_device) |
39 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) | 40 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
40 | return PCIBIOS_DEVICE_NOT_FOUND; | 41 | return PCIBIOS_DEVICE_NOT_FOUND; |
41 | 42 | ||
42 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) | 43 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) |
43 | if (bus->number != hose->first_busno) | 44 | if (bus->number != hose->first_busno) |
44 | cfg_type = 1; | 45 | cfg_type = 1; |
@@ -51,9 +52,12 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
51 | else | 52 | else |
52 | reg = offset & 0xfc; | 53 | reg = offset & 0xfc; |
53 | 54 | ||
54 | PCI_CFG_OUT(hose->cfg_addr, | 55 | if (hose->indirect_type & PPC_INDIRECT_TYPE_BIG_ENDIAN) |
55 | (0x80000000 | (bus_no << 16) | 56 | out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | |
56 | | (devfn << 8) | reg | cfg_type)); | 57 | (devfn << 8) | reg | cfg_type)); |
58 | else | ||
59 | out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | | ||
60 | (devfn << 8) | reg | cfg_type)); | ||
57 | 61 | ||
58 | /* | 62 | /* |
59 | * Note: the caller has already checked that offset is | 63 | * Note: the caller has already checked that offset is |
@@ -83,6 +87,13 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
83 | u8 cfg_type = 0; | 87 | u8 cfg_type = 0; |
84 | u32 bus_no, reg; | 88 | u32 bus_no, reg; |
85 | 89 | ||
90 | if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) { | ||
91 | if (bus->number != hose->first_busno) | ||
92 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
93 | if (devfn != 0) | ||
94 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
95 | } | ||
96 | |||
86 | if (ppc_md.pci_exclude_device) | 97 | if (ppc_md.pci_exclude_device) |
87 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) | 98 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
88 | return PCIBIOS_DEVICE_NOT_FOUND; | 99 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -99,9 +110,12 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
99 | else | 110 | else |
100 | reg = offset & 0xfc; | 111 | reg = offset & 0xfc; |
101 | 112 | ||
102 | PCI_CFG_OUT(hose->cfg_addr, | 113 | if (hose->indirect_type & PPC_INDIRECT_TYPE_BIG_ENDIAN) |
103 | (0x80000000 | (bus_no << 16) | 114 | out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | |
104 | | (devfn << 8) | reg | cfg_type)); | 115 | (devfn << 8) | reg | cfg_type)); |
116 | else | ||
117 | out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | | ||
118 | (devfn << 8) | reg | cfg_type)); | ||
105 | 119 | ||
106 | /* surpress setting of PCI_PRIMARY_BUS */ | 120 | /* surpress setting of PCI_PRIMARY_BUS */ |
107 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) | 121 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) |
@@ -135,24 +149,15 @@ static struct pci_ops indirect_pci_ops = | |||
135 | }; | 149 | }; |
136 | 150 | ||
137 | void __init | 151 | void __init |
138 | setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr, | 152 | setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data, u32 flags) |
139 | void __iomem * cfg_data) | ||
140 | { | ||
141 | hose->cfg_addr = cfg_addr; | ||
142 | hose->cfg_data = cfg_data; | ||
143 | hose->ops = &indirect_pci_ops; | ||
144 | } | ||
145 | |||
146 | void __init | ||
147 | setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) | ||
148 | { | 153 | { |
149 | unsigned long base = cfg_addr & PAGE_MASK; | 154 | unsigned long base = cfg_addr & PAGE_MASK; |
150 | void __iomem *mbase, *addr, *data; | 155 | void __iomem *mbase; |
151 | 156 | ||
152 | mbase = ioremap(base, PAGE_SIZE); | 157 | mbase = ioremap(base, PAGE_SIZE); |
153 | addr = mbase + (cfg_addr & ~PAGE_MASK); | 158 | hose->cfg_addr = mbase + (cfg_addr & ~PAGE_MASK); |
154 | if ((cfg_data & PAGE_MASK) != base) | 159 | if ((cfg_data & PAGE_MASK) != base) |
155 | mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); | 160 | mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); |
156 | data = mbase + (cfg_data & ~PAGE_MASK); | 161 | hose->cfg_data = mbase + (cfg_data & ~PAGE_MASK); |
157 | setup_indirect_pci_nomap(hose, addr, data); | 162 | hose->ops = &indirect_pci_ops; |
158 | } | 163 | } |